protected virtual void EmitPropertyMethod(PropertyDeclaration propertyDeclaration, Accessor accessor, bool setter) { var memberResult = this.Emitter.Resolver.ResolveNode(propertyDeclaration, this.Emitter) as MemberResolveResult; if (memberResult != null && (memberResult.Member.Attributes.Any(a => a.AttributeType.FullName == "Bridge.FieldPropertyAttribute") || (propertyDeclaration.Getter.IsNull && propertyDeclaration.Setter.IsNull))) { return; } if (!accessor.IsNull && this.Emitter.GetInline(accessor) == null) { this.EnsureComma(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); if (setter) { this.AddLocals(new ParameterDeclaration[] { new ParameterDeclaration { Name = "value" } }, accessor.Body); } var overloads = OverloadsCollection.Create(this.Emitter, propertyDeclaration, setter); string name = overloads.GetOverloadName(); this.Write((setter ? "set" : "get") + name); this.WriteColon(); this.WriteFunction(); this.WriteOpenParentheses(); this.Write(setter ? "value" : ""); this.WriteCloseParentheses(); this.WriteSpace(); var script = this.Emitter.GetScript(accessor); if (script == null) { accessor.Body.AcceptVisitor(this.Emitter); } else { this.BeginBlock(); foreach (var line in script) { this.Write(line); this.WriteNewLine(); } this.EndBlock(); } this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); this.Emitter.Comma = true; } }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { bool addClose = false; string leftInterfaceTempVar = null; if (orr.OperatorType == ExpressionType.OrElse || orr.OperatorType == ExpressionType.AndAlso) { var orElse = orr.OperatorType == ExpressionType.OrElse; var left = orr.Operands[0]; var memberTargetrr = left as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(left is ThisResolveResult || left is TypeResolveResult || left is LocalResolveResult || left is ConstantResolveResult || isField)) { this.WriteOpenParentheses(); leftInterfaceTempVar = this.GetTempVarName(); this.Write(leftInterfaceTempVar); this.Write(" = "); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.WriteComma(); addClose = true; } var m = FindOperatorTrueOrFalse(left.Type, orElse); this.Write(BridgeTypes.ToJsName(m.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, m).GetOverloadName()); this.WriteOpenParentheses(); if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.WriteCloseParentheses(); this.Write(" ? "); if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } this.Write(" : "); } if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT; switch (this.BinaryOperatorExpression.Operator) { case BinaryOperatorType.GreaterThan: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.GreaterThanOrEqual: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.Equality: action = JS.Funcs.Math.LIFTEQ; break; case BinaryOperatorType.InEquality: action = JS.Funcs.Math.LIFTNE; break; case BinaryOperatorType.LessThan: action = JS.Funcs.Math.LIFTCMP; break; case BinaryOperatorType.LessThanOrEqual: action = JS.Funcs.Math.LIFTCMP; break; } this.Write(action + "("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } if (leftInterfaceTempVar != null) { this.Write(leftInterfaceTempVar); this.Write(", "); binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); } else { new ExpressionListBlock(this.Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null, null, 0).Emit(); } this.WriteCloseParentheses(); if (addClose) { this.WriteCloseParentheses(); } return(true); } } return(false); }
protected virtual bool WriteObject(string objectName, List <TypeConfigItem> members, string format, string interfaceFormat) { bool hasProperties = HasProperties(objectName, members); int pos = 0; IWriterInfo writer = null; bool beginBlock = false; if (hasProperties && objectName != null && !IsObjectLiteral) { beginBlock = true; pos = Emitter.Output.Length; writer = SaveWriter(); EnsureComma(); Write(objectName); WriteColon(); BeginBlock(); } bool isProperty = JS.Fields.PROPERTIES == objectName; bool isField = JS.Fields.FIELDS == objectName; int count = 0; foreach (var member in members) { object constValue = null; bool isPrimitive = false; bool write = false; bool writeScript = false; if (member.Initializer is PrimitiveExpression primitiveExpr) { //isPrimitive = true; constValue = primitiveExpr.Value; ResolveResult rr = null; if (member.VarInitializer != null) { rr = Emitter.Resolver.ResolveNode(member.VarInitializer); } else { rr = Emitter.Resolver.ResolveNode(member.Entity); } if (rr != null && rr.Type.Kind == TypeKind.Enum) { constValue = Helpers.GetEnumValue(Emitter, rr.Type, constValue); writeScript = true; } } if (constValue is RawValue) { constValue = constValue.ToString(); write = true; writeScript = false; } var isNull = member.Initializer.IsNull || member.Initializer is NullReferenceExpression || member.Initializer.Parent == null; if (!isNull && !isPrimitive) { var constrr = Emitter.Resolver.ResolveNode(member.Initializer); if (constrr != null && constrr.IsCompileTimeConstant) { //isPrimitive = true; constValue = constrr.ConstantValue; var expectedType = Emitter.Resolver.Resolver.GetExpectedType(member.Initializer); if (!expectedType.Equals(constrr.Type) && expectedType.Kind != TypeKind.Dynamic) { try { constValue = Convert.ChangeType(constValue, ReflectionHelper.GetTypeCode(expectedType)); } catch (Exception) { Logger.ZLogWarning("FieldBlock: Convert.ChangeType is failed. Value type: {0}, Target type: {1}", constrr.Type.FullName, expectedType.FullName); } } if (constrr.Type.Kind == TypeKind.Enum) { constValue = Helpers.GetEnumValue(Emitter, constrr.Type, constrr.ConstantValue); } writeScript = true; } } var isNullable = false; if (isPrimitive && constValue is AstType) { var itype = Emitter.Resolver.ResolveNode((AstType)constValue); if (NullableType.IsNullable(itype.Type)) { isNullable = true; } } string tpl = null; IMember templateMember = null; MemberResolveResult init_rr = null; if (isField && member.VarInitializer != null) { init_rr = Emitter.Resolver.ResolveNode(member.VarInitializer) as MemberResolveResult; tpl = init_rr != null?Emitter.GetInline(init_rr.Member) : null; if (tpl != null) { templateMember = init_rr.Member; } } bool isAutoProperty = false; if (isProperty) { var member_rr = Emitter.Resolver.ResolveNode(member.Entity) as MemberResolveResult; var property = (IProperty)member_rr.Member; isAutoProperty = Helpers.IsAutoProperty(property); } bool written = false; if (!isNull && (!isPrimitive || constValue is AstType || tpl != null) && !(isProperty && !IsObjectLiteral && !isAutoProperty)) { string value = null; bool needContinue = false; string defValue = ""; if (!isPrimitive) { var oldWriter = SaveWriter(); NewWriter(); member.Initializer.AcceptVisitor(Emitter); value = Emitter.Output.ToString(); RestoreWriter(oldWriter); ResolveResult rr = null; AstType astType = null; if (member.VarInitializer != null) { rr = Emitter.Resolver.ResolveNode(member.VarInitializer); } else { astType = member.Entity.ReturnType; rr = Emitter.Resolver.ResolveNode(member.Entity); } constValue = Inspector.GetDefaultFieldValue(rr.Type, astType); if (rr.Type.Kind == TypeKind.Enum) { constValue = Helpers.GetEnumValue(Emitter, rr.Type, constValue); } isNullable = NullableType.IsNullable(rr.Type); needContinue = constValue is IType; writeScript = true; /*if (needContinue && !(member.Initializer is ObjectCreateExpression)) * { * defValue = " || " + Inspector.GetStructDefaultValue((IType)constValue, this.Emitter); * }*/ } else if (constValue is AstType) { value = isNullable ? "null" : Inspector.GetStructDefaultValue((AstType)constValue, Emitter); constValue = value; write = true; needContinue = !isProperty && !isNullable; } var name = member.GetName(Emitter); bool isValidIdentifier = Helpers.IsValidIdentifier(name); if (isProperty && isPrimitive) { constValue = "null"; if (IsObjectLiteral) { written = true; if (isValidIdentifier) { Write(string.Format("this.{0} = {1};", name, value)); } else { Write(string.Format("this[{0}] = {1};", ToJavaScript(name, Emitter), value)); } WriteNewLine(); } else { Injectors.Add(string.Format(name.StartsWith("\"") || !isValidIdentifier ? "this[{0}] = {1};" : "this.{0} = {1};", isValidIdentifier ? name : ToJavaScript(name, Emitter), value)); } } else { if (IsObjectLiteral) { written = true; if (isValidIdentifier) { Write(string.Format("this.{0} = {1};", name, value + defValue)); } else { Write(string.Format("this[{0}] = {1};", ToJavaScript(name, Emitter), value + defValue)); } WriteNewLine(); } else if (tpl != null) { if (!tpl.Contains("{0}")) { tpl = tpl + " = {0};"; } string v = null; if (!isNull && (!isPrimitive || constValue is AstType)) { v = value + defValue; } else { if (write) { v = constValue != null?constValue.ToString() : ""; } else if (writeScript) { v = ToJavaScript(constValue, Emitter); } else { var oldWriter = SaveWriter(); NewWriter(); member.Initializer.AcceptVisitor(Emitter); v = Emitter.Output.ToString(); RestoreWriter(oldWriter); } } tpl = Helpers.ConvertTokens(Emitter, tpl, templateMember); tpl = tpl.Replace("{this}", "this").Replace("{0}", v); if (!tpl.EndsWith(";")) { tpl += ";"; } Injectors.Add(tpl); } else { bool isDefaultInstance = Emitter.Resolver.ResolveNode(member.Initializer) is CSharpInvocationResolveResult rr && rr.Member.SymbolKind == SymbolKind.Constructor && rr.Arguments.Count == 0 && rr.InitializerStatements.Count == 0 && rr.Type.Kind == TypeKind.Struct; if (!isDefaultInstance) { if (isField && !isValidIdentifier) { Injectors.Add(string.Format("this[{0}] = {1};", name.StartsWith("\"") ? name : ToJavaScript(name, Emitter), value + defValue)); } else { Injectors.Add(string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value + defValue)); } } } } } count++; if (written) { continue; } bool withoutTypeParams = true; MemberResolveResult m_rr = null; if (member.Entity != null) { m_rr = Emitter.Resolver.ResolveNode(member.Entity) as MemberResolveResult; if (m_rr != null) { withoutTypeParams = OverloadsCollection.ExcludeTypeParameterForDefinition(m_rr); } } var mname = member.GetName(Emitter, withoutTypeParams); if (TypeInfo.IsEnum && m_rr != null) { mname = Emitter.GetEntityName(m_rr.Member); } bool isValid = Helpers.IsValidIdentifier(mname); if (!isValid) { if (IsObjectLiteral) { mname = "[" + ToJavaScript(mname, Emitter) + "]"; } else { mname = ToJavaScript(mname, Emitter); } } if (IsObjectLiteral) { WriteThis(); if (isValid) { WriteDot(); } Write(mname); Write(" = "); } else { EnsureComma(); XmlToJsDoc.EmitComment(this, member.Entity, null, member.Entity is FieldDeclaration ? member.VarInitializer : null); Write(mname); WriteColon(); } bool close = false; if (isProperty && !IsObjectLiteral && !isAutoProperty) { var oldTempVars = Emitter.TempVariables; BeginBlock(); new VisitorPropertyBlock(Emitter, (PropertyDeclaration)member.Entity).Emit(); WriteNewLine(); EndBlock(); Emitter.Comma = true; Emitter.TempVariables = oldTempVars; continue; } if (constValue is AstType || constValue is IType) { Write("null"); if (!isNullable) { var name = member.GetName(Emitter); bool isValidIdentifier = Helpers.IsValidIdentifier(name); var value = constValue is AstType?Inspector.GetStructDefaultValue((AstType)constValue, Emitter) : Inspector.GetStructDefaultValue((IType)constValue, Emitter); if (!isValidIdentifier) { Injectors.Insert(BeginCounter++, string.Format("this[{0}] = {1};", name.StartsWith("\"") ? name : ToJavaScript(name, Emitter), value)); } else { Injectors.Insert(BeginCounter++, string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value)); } } } else if (write) { Write(constValue); } else if (writeScript) { WriteScript(constValue); } else { member.Initializer.AcceptVisitor(Emitter); } if (close) { Write(" }"); } if (IsObjectLiteral) { WriteSemiColon(true); } Emitter.Comma = true; } if (count > 0 && objectName != null && !IsObjectLiteral) { WriteNewLine(); EndBlock(); } else if (beginBlock) { Emitter.IsNewLine = writer.IsNewLine; Emitter.ResetLevel(writer.Level); Emitter.Comma = writer.Comma; Emitter.Output.Length = pos; } return(count > 0); }
private void WriteInterfaceMember(string interfaceTempVar, MemberResolveResult resolveResult, bool isSetter, string prefix = null) { var itypeDef = resolveResult.Member.DeclaringTypeDefinition; var externalInterface = this.Emitter.Validator.IsExternalInterface(itypeDef); bool variance = MetadataUtils.IsJsGeneric(itypeDef, this.Emitter) && itypeDef.TypeParameters != null && itypeDef.TypeParameters.Any(typeParameter => typeParameter.Variance != VarianceModifier.Invariant); if (interfaceTempVar != null && externalInterface == null && !variance) { this.WriteComma(); this.Write(interfaceTempVar); } if (externalInterface != null && externalInterface.IsDualImplementation || variance) { if (interfaceTempVar != null) { this.WriteCloseParentheses(); } this.WriteOpenBracket(); this.Write(JS.Funcs.BRIDGE_GET_I); this.WriteOpenParentheses(); if (interfaceTempVar != null) { this.Write(interfaceTempVar); } else { this.WriteSimpleTarget(resolveResult); } this.WriteComma(); var interfaceName = OverloadsCollection.Create(Emitter, resolveResult.Member, isSetter).GetOverloadName(false, prefix); if (interfaceName.StartsWith("\"")) { this.Write(interfaceName); } else { this.WriteScript(interfaceName); } if (variance) { this.WriteComma(); this.WriteScript(OverloadsCollection.Create(Emitter, resolveResult.Member, isSetter).GetOverloadName(false, prefix, withoutTypeParams: true)); } /*this.WriteComma(); * this.WriteScript(OverloadsCollection.Create(Emitter, resolveResult.Member, isSetter).GetOverloadName(true, prefix));*/ this.Write(")"); this.WriteCloseBracket(); return; } this.WriteOpenBracket(); this.Write(OverloadsCollection.Create(Emitter, resolveResult.Member, isSetter).GetOverloadName(externalInterface != null && externalInterface.IsSimpleImplementation, prefix)); this.WriteCloseBracket(); if (interfaceTempVar != null) { this.WriteCloseParentheses(); } }
protected void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { var typeDef = this.Emitter.GetTypeDefinition(); var overloads = OverloadsCollection.Create(this.Emitter, methodDeclaration); if (overloads.HasOverloads) { string name = overloads.GetOverloadName(); this.Write(name); } else { this.Write(this.Emitter.GetEntityName(methodDeclaration)); } var isGeneric = methodDeclaration.TypeParameters.Count > 0; if (isGeneric) { bool needComma = false; this.Write("<"); foreach (var p in methodDeclaration.TypeParameters) { if (needComma) { this.WriteComma(); } needComma = true; this.Write(p.Name); } this.Write(">"); this.WriteOpenParentheses(); var comma = false; foreach (var p in methodDeclaration.TypeParameters) { if (comma) { this.WriteComma(); } this.Write(p.Name); this.WriteColon(); this.WriteOpenBrace(); this.Write("prototype"); this.WriteColon(); this.Write(p.Name); this.WriteCloseBrace(); comma = true; } this.WriteCloseParentheses(); this.WriteColon(); this.WriteOpenBrace(); this.WriteSpace(); } this.EmitMethodParameters(methodDeclaration.Parameters, methodDeclaration); this.WriteColon(); var retType = BridgeTypes.ToJsName(methodDeclaration.ReturnType, this.Emitter); retType = EmitBlock.HandleType(retType); this.Write(retType); if (isGeneric) { this.WriteSpace(); this.WriteCloseBrace(); } this.WriteSemiColon(); this.WriteNewLine(); }
public static bool CheckConversion(ConversionBlock block, Expression expression) { Conversion conversion = null; try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion == null) { return(false); } if (conversion.IsIdentityConversion) { return(false); } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return(false); } if (conversion.IsLifted && !isNumLifted) { block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return(conversion.IsLifted); } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return(conversion.IsLifted); } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return(conversion.IsLifted); } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (conversion.IsLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); } return(true); } // Still returns true if Nullable.lift( was written. return(conversion.IsLifted); } catch { } return(false); }
private void HandleDecimal(ResolveResult resolveOperator) { if (this.AssignmentExpression.Operator == AssignmentOperatorType.Assign) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Right }, null).Emit(); return; } var orr = resolveOperator as OperatorResolveResult; var method = orr != null ? orr.UserDefinedOperatorMethod : null; var assigmentType = Helpers.TypeOfAssignment(this.AssignmentExpression.Operator); if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(assigmentType); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = this.Emitter.GetInline(method); if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable."); string action = "lift2"; string op_name = null; switch (assigmentType) { case BinaryOperatorType.GreaterThan: op_name = "gt"; break; case BinaryOperatorType.GreaterThanOrEqual: op_name = "gte"; break; case BinaryOperatorType.Equality: op_name = "equals"; break; case BinaryOperatorType.InEquality: op_name = "ne"; break; case BinaryOperatorType.LessThan: op_name = "lt"; break; case BinaryOperatorType.LessThanOrEqual: op_name = "lte"; break; case BinaryOperatorType.Add: op_name = "add"; break; case BinaryOperatorType.Subtract: op_name = "sub"; break; case BinaryOperatorType.Multiply: op_name = "mul"; break; case BinaryOperatorType.Divide: op_name = "div"; break; case BinaryOperatorType.Modulus: op_name = "mod"; break; default: throw new ArgumentOutOfRangeException(); } this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null).Emit(); this.WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.AssignmentExpression, orr, method), inline).Emit(); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null).Emit(); this.WriteCloseParentheses(); } } }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; this.isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id) && resolveResult is LocalResolveResult) { var lrr = (LocalResolveResult)resolveResult; if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(lrr.Variable) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[lrr.Variable]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); return; } if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); /*if (this.Emitter.Validator.IsExternalType(resolveResult.Type.GetDefinition()) || resolveResult.Type.Kind == TypeKind.Enum) * { * this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); * } * else * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(resolveResult.Type, this.Emitter) + ")"); * }*/ return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; var isInvoke = identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression); if (memberResult != null && memberResult.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(memberResult.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inlineCode = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } if (string.IsNullOrEmpty(inlineCode) && memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var method = (IMethod)memberResult.Member; if (method.TypeArguments.Count > 0) { inlineCode = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasInline && inlineCode.StartsWith("<self>")) { hasThis = true; inlineCode = inlineCode.Substring(6); } if (hasThis) { Emitter.ThisRefCounter++; this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); /*if (!this.Emitter.Validator.IsExternalType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum) * { * this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); * } * else * { * this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { this.WriteThis(); } var oldInline = inlineCode; var thisArg = this.Emitter.Output.ToString(); int thisIndex = inlineCode.IndexOf("{this}"); inlineCode = inlineCode.Replace("{this}", thisArg); this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode, null, thisArg, range); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), oldInline, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else if (memberResult != null && memberResult.Member is IField && inlineCode.Contains("{0}")) { this.PushWriter(inlineCode, null, thisArg, range); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode)) { this.PushWriter(inlineCode, null, thisArg, range); } else { this.Write(inlineCode); } } return; } if (hasInline) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode)) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } return; } string appendAdditionalCode = null; if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { if (!string.IsNullOrEmpty(inlineCode)) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, identifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else { var resolvedMethod = (IMethod)memberResult.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_CACHE_BIND); this.WriteOpenParentheses(); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(memberResult.Member) && this.Emitter.IsInlineConst(memberResult.Member)) { this.WriteScript(memberResult.ConstantValue); return; } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { //this.Write(inlineCode); if (resolveResult is InvocationResolveResult || (memberResult.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } else if (memberResult.Member is IProperty) { var name = Helpers.GetPropertyRef(memberResult.Member, this.Emitter); this.WriteIdentifier(name); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.DEC); } this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.DEC); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); } else { trg = "this"; } bool isBool = memberResult != null && NullableType.IsNullable(memberResult.Member.ReturnType) ? NullableType.GetUnderlyingType(memberResult.Member.ReturnType).IsKnownType(KnownTypeCode.Boolean) : memberResult.Member.ReturnType.IsKnownType(KnownTypeCode.Boolean); bool skipGet = false; var orr = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter) as OperatorResolveResult; bool special = orr != null && orr.IsLiftedOperator; if (!special && isBool && (this.Emitter.AssignmentType == AssignmentOperatorType.BitwiseAnd || this.Emitter.AssignmentType == AssignmentOperatorType.BitwiseOr)) { skipGet = true; } if (skipGet) { this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "({0})")); } else { this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), "()", "{0})")); } } else { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is IEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); this.Write( OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member, true)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); string name = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); if (isRefArg) { this.WriteScript(name); } else if (memberResult.Member is IField) { this.WriteIdentifier(name); } else { this.Write(name); } } else { this.Write(resolveResult.ToString()); } } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); }
protected void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { foreach (var attrSection in methodDeclaration.Attributes) { foreach (var attr in attrSection.Attributes) { var rr = this.Emitter.Resolver.ResolveNode(attr.Type, this.Emitter); if (rr.Type.FullName == "Bridge.ExternalAttribute" || rr.Type.FullName == "Bridge.IgnoreAttribute") { return; } else if (rr.Type.FullName == "Bridge.InitAttribute") { int initPosition = 0; if (attr.HasArgumentList) { if (attr.Arguments.Any()) { var argExpr = attr.Arguments.First(); var argrr = this.Emitter.Resolver.ResolveNode(argExpr, this.Emitter); if (argrr.ConstantValue is int) { initPosition = (int)argrr.ConstantValue; } } } if (initPosition > 0) { return; } } } } //this.EnsureComma(); this.EnsureNewLine(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(methodDeclaration.Parameters, methodDeclaration.Body); var typeDef = this.Emitter.GetTypeDefinition(); var overloads = OverloadsCollection.Create(this.Emitter, methodDeclaration); XmlToJsDoc.EmitComment(this, this.MethodDeclaration); string name = overloads.GetOverloadName(); TransformCtx.CurClassMethodNames.Add(new TransformCtx.MethodInfo() { Name = name, IsPrivate = methodDeclaration.HasModifier(Modifiers.Private), }); this.Write(name); this.WriteEqualsSign(); /* * if (methodDeclaration.TypeParameters.Count > 0) * { * this.WriteFunction(); * this.EmitTypeParameters(methodDeclaration.TypeParameters, methodDeclaration); * this.WriteSpace(); * this.BeginBlock(); * this.WriteReturn(true); * this.Write("Bridge.fn.bind(this, "); * }*/ this.WriteFunction(); this.EmitMethodParameters(methodDeclaration.Parameters, methodDeclaration, true); if (methodDeclaration.TypeParameters.Count > 0) { if (methodDeclaration.Parameters.Count > 0 || !methodDeclaration.HasModifier(Modifiers.Static)) { this.WriteComma(); } this.EmitTypeParameters(methodDeclaration.TypeParameters, methodDeclaration); } this.WriteCloseParentheses(); this.WriteSpace(); var script = this.Emitter.GetScript(methodDeclaration); if (script == null) { if (methodDeclaration.HasModifier(Modifiers.Async)) { new AsyncBlock(this.Emitter, methodDeclaration).Emit(); } else { this.BeginFunctionBlock(); bool isYieldExists = YieldBlock.HasYield(methodDeclaration.Body); if (isYieldExists) { YieldBlock.EmitYield(this, null); } else { this.ConvertParamsToReferences(methodDeclaration.Parameters); } MarkTempVars(); methodDeclaration.Body.AcceptVisitor(this.Emitter); EmitTempVars(); if (isYieldExists) { var returnResolveResult = this.Emitter.Resolver.ResolveNode(methodDeclaration.ReturnType, this.Emitter); YieldBlock.EmitYieldReturn(this, returnResolveResult.Type); } else { PrimitiveType returnType = methodDeclaration.ReturnType as PrimitiveType; if (returnType != null) { if (returnType.KnownTypeCode == ICSharpCode.NRefactory.TypeSystem.KnownTypeCode.Void) { string refArgsString = GetRefArgsString(this.Emitter, methodDeclaration); if (refArgsString != null) { this.WriteReturn(true); this.Write(refArgsString); this.WriteNewLine(); } } } } this.EndFunctionBlock(); } } else { this.BeginBlock(); foreach (var line in script) { this.Write(line); this.WriteNewLine(); } this.EndBlock(); } /* * if (methodDeclaration.TypeParameters.Count > 0) * { * this.Write(");"); * this.WriteNewLine(); * this.EndBlock(); * }*/ this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); this.Emitter.Comma = true; }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; bool isConstTarget = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (targetrr is ConstantResolveResult) { isConstTarget = true; } var memberTargetrr = targetrr as MemberResolveResult; if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && this.Emitter.Validator.EnumEmitMode(memberTargetrr.Type) == 2) { isConstTarget = true; } if (memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression)) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } if (resolveResult is DynamicInvocationResolveResult) { resolveResult = ((DynamicInvocationResolveResult)resolveResult).Target; } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; var globalTarget = member != null?this.Emitter.IsGlobalTarget(member.Member) : null; if (globalTarget != null && globalTarget.Item1) { var target = globalTarget.Item2; if (!string.IsNullOrWhiteSpace(target)) { bool assign = false; var memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent; var targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression; var assignment = memberExpression as AssignmentExpression; if (assignment != null && assignment.Right == targetExpression) { assign = true; } else { var varInit = memberExpression as VariableInitializer; if (varInit != null && varInit.Initializer == targetExpression) { assign = true; } else if (memberExpression is InvocationExpression) { var targetInvocation = (InvocationExpression)memberExpression; if (targetInvocation.Arguments.Any(a => a == targetExpression)) { assign = true; } } } if (assign) { if (resolveResult is InvocationResolveResult) { this.PushWriter(target); } else { this.Write(target); } return; } } if (resolveResult is InvocationResolveResult) { this.PushWriter(""); } return; } Tuple <bool, bool, string> inlineInfo = member != null?this.Emitter.GetInlineCode(memberReferenceExpression) : null; //string inline = member != null ? this.Emitter.GetInline(member.Member) : null; string inline = inlineInfo != null ? inlineInfo.Item3 : null; bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && inline.Contains("{this}"); if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; inline = inline.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference"); } else { this.Write(inline); } } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(member.ConstantValue); } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { var r = new Regex(@"([$\w\.]+)\(\s*\S.*\)"); var match = r.Match(inline); if (match.Success) { this.Write(match.Groups[1].Value); } else { throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference"); } } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as DefaultResolvedTypeDefinition; if (typeDef != null) { var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsIgnoreType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3) { string enumStringName = member.Member.Name; var attr = Helpers.GetInheritedAttribute(member.Member, Translator.Bridge_ASSEMBLY + ".NameAttribute"); if (attr != null) { enumStringName = this.Emitter.GetEntityName(member.Member); } else { switch (enumMode) { case 3: enumStringName = Object.Net.Utilities.StringUtils.ToLowerCamelCase(member.Member.Name); break; case 4: break; case 5: enumStringName = enumStringName.ToLowerInvariant(); break; case 6: enumStringName = enumStringName.ToUpperInvariant(); break; } } this.WriteScript(enumStringName); return; } } } if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition()) || typeResolveResult.Type.Kind == TypeKind.Enum; if (isNative) { this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); } else { this.Write("Bridge.get(" + BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter) + ")"); } return; } else if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); if (!isStatic) { this.Write(")"); } return; } else { bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } } if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } } var targetResolveResult = targetrr as MemberResolveResult; if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null) { this.WriteDot(); } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { var proto = false; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && member != null) { var prop = member.Member as IProperty; if (prop != null && (prop.IsVirtual || prop.IsOverride)) { proto = true; } } if (Helpers.IsFieldProperty(member.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isNullable = NullableType.IsNullable(member.Member.ReturnType); bool isDecimal = Helpers.IsDecimalType(member.Member.ReturnType, this.Emitter.Resolver); if (isStatement) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } } else { if (targetVar != null) { this.Write(targetVar); } else { if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); this.WriteCloseParentheses(); } } else { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); bool isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement; if (isPreOp) { if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } if (targetVar != null) { this.RemoveTempVar(targetVar); } } else { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { //Only write "()" if the property is NOT on an external class //And if the property has a body. When it has a body, we generate a javascript //getter function and need to actually invoke the function var declaringTypeDef = member.Member.DeclaringTypeDefinition; if (declaringTypeDef != null && !Emitter.Validator.IsIgnoreType(declaringTypeDef)) { IProperty prop = null; if (declaringTypeDef.Properties != null) { prop = declaringTypeDef.Properties.FirstOrDefault(p => p.FullName == member.Member.FullName); } if (prop != null && !prop.Equals(default(IProperty)) && prop.Getter != null && !prop.Getter.BodyRegion.IsEmpty) { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } } } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { if (targetVar != null) { this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true), proto ? ".call(this, " : "(", targetVar, ".", Helpers.GetPropertyRef(member.Member, this.Emitter, false), proto ? ".call(this)" : "()", "{0})"), () => { this.RemoveTempVar(targetVar); }); } else { var oldWriter = this.SaveWriter(); this.NewWriter(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; var trg = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true), proto ? ".call(this, " : "(", trg, ".", Helpers.GetPropertyRef(member.Member, this.Emitter, false), proto ? ".call(this)" : "()", "{0})")); } } else { if (proto) { this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + ".call(this, {0})"); } else { //Property setter //If a property has a body, call the property like a function .Interaction(2); //If no body, then .Interaction = 2; var declaringTypeDef = member.Member.DeclaringTypeDefinition; IProperty prop = null; if (declaringTypeDef != null && declaringTypeDef.Properties != null) { prop = declaringTypeDef.Properties.FirstOrDefault(p => p.FullName == member.Member.FullName); } var propRef = Helpers.GetPropertyRef(member.Member, this.Emitter, true); if (prop != null && !prop.Equals(default(IProperty)) && prop.Setter != null && !prop.Setter.BodyRegion.IsEmpty) { this.PushWriter(propRef + "({0})"); } else { this.PushWriter(propRef + " = {0}"); } } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(member.ConstantValue); } else { this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName()); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName()); } } else if (member.Member is DefaultResolvedEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add_" : "remove_"); this.Write( OverloadsCollection.Create(this.Emitter, member.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); this.WriteOpenParentheses(); } else { this.Write(this.Emitter.GetEntityName(member.Member, true)); } } else { this.Write(this.Emitter.GetEntityName(member.Member)); } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
protected virtual void EmitBaseConstructor(ConstructorDeclaration ctor, string ctorName, bool isObjectLiteral) { var initializer = ctor.Initializer != null && !ctor.Initializer.IsNull ? ctor.Initializer : new ConstructorInitializer() { ConstructorInitializerType = ConstructorInitializerType.Base }; bool appendScope = false; bool isBaseObjectLiteral = false; if (initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { var baseType = Emitter.GetBaseTypeDefinition(); //var baseName = JS.Funcs.CONSTRUCTOR; string baseName = null; isBaseObjectLiteral = Emitter.Validator.IsObjectLiteral(baseType); if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(ctor.Initializer)).Member; var overloads = OverloadsCollection.Create(Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } } string name = null; if (TypeInfo.GetBaseTypes(Emitter).Any()) { name = H5Types.ToJsName(TypeInfo.GetBaseClass(Emitter), Emitter); } else { name = H5Types.ToJsName(baseType, Emitter); } if (!isObjectLiteral && isBaseObjectLiteral) { Write(JS.Types.H5.COPY_PROPERTIES); WriteOpenParentheses(); Write("this, "); } Write(name, "."); if (baseName == null) { var baseIType = Emitter.H5Types.Get(baseType).Type; var baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.Count == 0); if (baseCtor == null) { baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.All(p => p.IsOptional)); } if (baseCtor == null) { baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.Count == 1 && c.Parameters.First().IsParams); } if (baseCtor != null) { baseName = OverloadsCollection.Create(Emitter, baseCtor).GetOverloadName(); } else { baseName = JS.Funcs.CONSTRUCTOR; } } Write(baseName); if (!isObjectLiteral) { WriteCall(); appendScope = true; } } else { // this.WriteThis(); string name = H5Types.ToJsName(TypeInfo.Type, Emitter); Write(name); WriteDot(); var baseName = JS.Funcs.CONSTRUCTOR; var member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(ctor.Initializer)).Member; var overloads = OverloadsCollection.Create(Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } Write(baseName); if (!isObjectLiteral) { WriteCall(); appendScope = true; } } int openPos = Emitter.Output.Length; WriteOpenParentheses(); if (appendScope) { WriteThis(); if (initializer.Arguments.Count > 0) { WriteComma(); } } if (initializer.Arguments.Count > 0) { var argsInfo = new ArgumentsInfo(Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } if (!isObjectLiteral && isBaseObjectLiteral) { WriteCloseParentheses(); } WriteCloseParentheses(); WriteSemiColon(); if (!isObjectLiteral) { WriteNewLine(); } }
private void HandleType(ResolveResult resolveOperator, string variable, string op_name, KnownTypeCode typeCode) { if (this.AssignmentExpression.Operator == AssignmentOperatorType.Assign) { if (variable != null) { this.Write(variable); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Right }, null, null, 0).Emit(); } return; } var orr = resolveOperator as OperatorResolveResult; var method = orr != null ? orr.UserDefinedOperatorMethod : null; var assigmentType = Helpers.TypeOfAssignment(this.AssignmentExpression.Operator); if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(assigmentType); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = this.Emitter.GetInline(method); if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.AssignmentExpression, orr, method), inline).Emit(); } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); this.Write(", " + variable); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.WriteCloseParentheses(); } } else { if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else { this.AssignmentExpression.Left.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.AssignmentExpression.Right.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } } }
protected void VisitAsyncForeachStatement() { ForeachStatement foreachStatement = this.ForeachStatement; if (foreachStatement.EmbeddedStatement is EmptyStatement) { return; } var oldValue = this.Emitter.ReplaceAwaiterByVar; var jumpStatements = this.Emitter.JumpStatements; this.Emitter.JumpStatements = new List <IJumpInfo>(); this.WriteAwaiters(foreachStatement.InExpression); bool containsAwaits = false; var awaiters = this.GetAwaiters(foreachStatement.EmbeddedStatement); if (awaiters != null && awaiters.Length > 0) { containsAwaits = true; } this.Emitter.ReplaceAwaiterByVar = true; if (!containsAwaits) { this.VisitForeachStatement(oldValue); return; } var iteratorName = this.AddLocal(this.GetTempVarName(), null, AstType.Null); var for_rr = (ForEachResolveResult)this.Emitter.Resolver.ResolveNode(foreachStatement, this.Emitter); var get_rr = for_rr.GetEnumeratorCall as InvocationResolveResult; var in_rr = this.Emitter.Resolver.ResolveNode(foreachStatement.InExpression, this.Emitter); var inline = get_rr != null?this.Emitter.GetInline(get_rr.Member) : null; var checkEnum = in_rr.Type.Kind != TypeKind.Array && !in_rr.Type.IsKnownType(KnownTypeCode.String) && !in_rr.Type.IsKnownType(KnownTypeCode.Array); var isGenericEnumerable = for_rr.CollectionType.IsParameterized && for_rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable"; var emitInline = checkEnum && !isGenericEnumerable && inline != null; this.Write(iteratorName, " = "); if (!emitInline) { this.Write(JS.Funcs.BRIDGE_GET_ENUMERATOR); this.WriteOpenParentheses(); foreachStatement.InExpression.AcceptVisitor(this.Emitter); } if (checkEnum) { if (for_rr.CollectionType.IsParameterized && for_rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable") { this.WriteComma(false); this.Write(BridgeTypes.ToJsName(((ParameterizedType)for_rr.CollectionType).TypeArguments[0], this.Emitter)); } else if (get_rr != null) { if (inline != null) { var argsInfo = new ArgumentsInfo(this.Emitter, foreachStatement.InExpression, get_rr); new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { var name = OverloadsCollection.Create(this.Emitter, get_rr.Member).GetOverloadName(); if (name != "getEnumerator" && name != "System$Collections$IEnumerable$getEnumerator") { this.WriteComma(false); this.WriteScript(name); } } } } this.Emitter.ReplaceAwaiterByVar = oldValue; if (!emitInline) { this.WriteCloseParentheses(); } this.WriteSemiColon(); this.WriteNewLine(); this.Write(JS.Vars.ASYNC_STEP + " = " + this.Emitter.AsyncBlock.Step + ";"); this.WriteNewLine(); this.Write("continue;"); this.WriteNewLine(); IAsyncStep conditionStep = this.Emitter.AsyncBlock.AddAsyncStep(); this.WriteIf(); this.WriteOpenParentheses(); this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.MOVE_NEXT); this.WriteOpenCloseParentheses(); this.WriteCloseParentheses(); this.WriteSpace(); this.BeginBlock(); this.PushLocals(); var varName = this.AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType); this.WriteVar(); this.Write(varName + " = "); var rr = this.Emitter.Resolver.ResolveNode(foreachStatement, this.Emitter) as ForEachResolveResult; string castCode = this.GetCastCode(rr.ElementType, rr.ElementVariable.Type); if (castCode != null) { this.EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode); } else if (this.CastMethod != null) { this.Write(BridgeTypes.ToJsName(this.CastMethod.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, this.CastMethod).GetOverloadName()); this.WriteOpenParentheses(); var pos = this.Emitter.Output.Length; this.Write(iteratorName + "." + JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); this.WriteCloseParentheses(); } else { var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type); if (needCast) { this.Write(JS.Funcs.BRIDGE_CAST); this.WriteOpenParentheses(); } var pos = this.Emitter.Output.Length; this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); if (needCast) { this.Write(", ", BridgeTypes.ToJsName(rr.ElementVariable.Type, this.Emitter), ")"); } } this.WriteSemiColon(); this.WriteNewLine(); this.Write(JS.Vars.ASYNC_STEP + " = " + this.Emitter.AsyncBlock.Step + ";"); this.WriteNewLine(); this.Write("continue;"); BlockStatement block = foreachStatement.EmbeddedStatement as BlockStatement; var writer = this.SaveWriter(); this.Emitter.AsyncBlock.AddAsyncStep(); this.Emitter.IgnoreBlock = foreachStatement.EmbeddedStatement; var startCount = this.Emitter.AsyncBlock.Steps.Count; if (block != null) { block.AcceptChildren(this.Emitter); } else { foreachStatement.EmbeddedStatement.AcceptVisitor(this.Emitter); } IAsyncStep loopStep = null; if (this.Emitter.AsyncBlock.Steps.Count > startCount) { loopStep = this.Emitter.AsyncBlock.Steps.Last(); loopStep.JumpToStep = conditionStep.Step; } this.RestoreWriter(writer); if (!AbstractEmitterBlock.IsJumpStatementLast(this.Emitter.Output.ToString())) { this.Write(JS.Vars.ASYNC_STEP + " = " + conditionStep.Step + ";"); this.WriteNewLine(); this.Write("continue;"); this.WriteNewLine(); } this.PopLocals(); this.WriteNewLine(); this.EndBlock(); this.WriteNewLine(); var nextStep = this.Emitter.AsyncBlock.AddAsyncStep(); conditionStep.JumpToStep = nextStep.Step; if (this.Emitter.JumpStatements.Count > 0) { this.Emitter.JumpStatements.Sort((j1, j2) => - j1.Position.CompareTo(j2.Position)); foreach (var jump in this.Emitter.JumpStatements) { jump.Output.Insert(jump.Position, jump.Break ? nextStep.Step : conditionStep.Step); } } this.Emitter.JumpStatements = jumpStatements; }
protected void VisitForeachStatement(bool?replaceAwaiterByVar = null) { ForeachStatement foreachStatement = this.ForeachStatement; var jumpStatements = this.Emitter.JumpStatements; this.Emitter.JumpStatements = null; if (foreachStatement.EmbeddedStatement is EmptyStatement) { return; } var iteratorVar = this.GetTempVarName(); var iteratorName = this.AddLocal(iteratorVar, null, AstType.Null); var rr = (ForEachResolveResult)this.Emitter.Resolver.ResolveNode(foreachStatement, this.Emitter); var get_rr = rr.GetEnumeratorCall as InvocationResolveResult; var in_rr = this.Emitter.Resolver.ResolveNode(foreachStatement.InExpression, this.Emitter); var inline = get_rr != null?this.Emitter.GetInline(get_rr.Member) : null; var checkEnum = in_rr.Type.Kind != TypeKind.Array && !in_rr.Type.IsKnownType(KnownTypeCode.String) && !in_rr.Type.IsKnownType(KnownTypeCode.Array); var isGenericEnumerable = rr.CollectionType.IsParameterized && rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable"; var emitInline = checkEnum && !isGenericEnumerable && inline != null; this.Write(iteratorName, " = "); if (!emitInline) { this.Write(JS.Funcs.BRIDGE_GET_ENUMERATOR); this.WriteOpenParentheses(); foreachStatement.InExpression.AcceptVisitor(this.Emitter); } if (checkEnum) { if (isGenericEnumerable) { this.WriteComma(false); this.Write(BridgeTypes.ToJsName(((ParameterizedType)rr.CollectionType).TypeArguments[0], this.Emitter)); } else if (get_rr != null) { if (inline != null) { var argsInfo = new ArgumentsInfo(this.Emitter, foreachStatement.InExpression, get_rr); new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { var name = OverloadsCollection.Create(this.Emitter, get_rr.Member).GetOverloadName(); if (name != "getEnumerator" && name != "System$Collections$IEnumerable$getEnumerator") { this.WriteComma(false); this.WriteScript(name); } } } } if (!emitInline) { this.WriteCloseParentheses(); } this.WriteSemiColon(); this.WriteNewLine(); this.WriteTry(); this.BeginBlock(); this.WriteWhile(); this.WriteOpenParentheses(); this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.MOVE_NEXT); this.WriteOpenCloseParentheses(); this.WriteCloseParentheses(); this.WriteSpace(); this.BeginBlock(); this.PushLocals(); Action ac = () => { var varName = this.AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType); this.WriteVar(); this.Write(varName + " = "); string castCode = this.GetCastCode(rr.ElementType, rr.ElementVariable.Type); if (castCode != null) { this.EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode); } else if (this.CastMethod != null) { this.Write(BridgeTypes.ToJsName(this.CastMethod.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, this.CastMethod).GetOverloadName()); this.WriteOpenParentheses(); int pos = this.Emitter.Output.Length; this.Write(iteratorName + "." + JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); this.WriteCloseParentheses(); } else { var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type); if (needCast) { this.Write(JS.Funcs.BRIDGE_CAST); this.WriteOpenParentheses(); } int pos = this.Emitter.Output.Length; this.Write(iteratorName); this.WriteDot(); this.Write(JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, this.ForeachStatement.InExpression, this, pos); if (needCast) { this.Write(", ", BridgeTypes.ToJsName(rr.ElementVariable.Type, this.Emitter), ")"); } } this.WriteSemiColon(); this.WriteNewLine(); }; this.Emitter.BeforeBlock = ac; BlockStatement block = foreachStatement.EmbeddedStatement as BlockStatement; if (replaceAwaiterByVar.HasValue) { this.Emitter.ReplaceAwaiterByVar = replaceAwaiterByVar.Value; } if (block != null) { this.Emitter.NoBraceBlock = block; } foreachStatement.EmbeddedStatement.AcceptVisitor(this.Emitter); this.PopLocals(); if (!this.Emitter.IsNewLine) { this.WriteNewLine(); } this.EndBlock(); this.WriteNewLine(); this.EndBlock(); this.WriteFinally(); this.BeginBlock(); this.Write($"if ({JS.Types.Bridge.IS}({iteratorName}, {JS.Types.System.IDisposable.NAME})) "); this.BeginBlock(); this.Write($"{iteratorName}.{JS.Types.System.IDisposable.INTERFACE_DISPOSE}();"); this.WriteNewLine(); this.EndBlock(); this.WriteNewLine(); this.EndBlock(); this.Emitter.JumpStatements = jumpStatements; }
protected virtual void WriteObjectInitializer(IEnumerable <Expression> expressions, bool preserveMemberCase, TypeDefinition type, InvocationResolveResult rr) { bool needComma = false; List <string> names = new List <string>(); if (expressions != null) { foreach (Expression item in expressions) { NamedExpression namedExression = item as NamedExpression; NamedArgumentExpression namedArgumentExpression = item as NamedArgumentExpression; string name = namedExression != null ? namedExression.Name : namedArgumentExpression.Name; if (!preserveMemberCase) { name = Object.Net.Utilities.StringUtils.ToLowerCamelCase(name); } var itemrr = this.Emitter.Resolver.ResolveNode(item, this.Emitter) as MemberResolveResult; if (itemrr != null) { var oc = OverloadsCollection.Create(this.Emitter, itemrr.Member); name = oc.GetOverloadName(); } if (needComma) { this.WriteComma(); } needComma = true; Expression expression = namedExression != null ? namedExression.Expression : namedArgumentExpression.Expression; this.Write(name, ": "); expression.AcceptVisitor(this.Emitter); names.Add(name); } } if (this.Emitter.Validator.IsObjectLiteral(type)) { var key = BridgeTypes.GetTypeDefinitionKey(type); var tinfo = this.Emitter.Types.FirstOrDefault(t => t.Key == key); if (tinfo == null) { return; } var itype = tinfo.Type as ITypeDefinition; var mode = 0; if (rr != null) { if (rr.Member.Parameters.Count == 1 && rr.Member.Parameters.First().Type.FullName == "Bridge.DefaultValueMode") { var arg = rr.Arguments.FirstOrDefault(); if (arg != null && arg.ConstantValue != null) { mode = (int)arg.ConstantValue; } } else if (itype != null) { var attr = this.Emitter.Validator.GetAttribute(itype.Attributes, Translator.Bridge_ASSEMBLY + ".ObjectLiteralAttribute"); if (attr.PositionalArguments.Count > 0) { var value = attr.PositionalArguments.First().ConstantValue; if (value != null && value is int) { mode = (int)value; } } } } if (mode != 0) { var members = tinfo.InstanceConfig.Fields.Concat(tinfo.InstanceConfig.Properties); if (members.Any()) { foreach (var member in members) { if (mode == 1 && (member.VarInitializer == null || member.VarInitializer.Initializer.IsNull)) { continue; } var name = member.GetName(this.Emitter); if (!preserveMemberCase) { name = Object.Net.Utilities.StringUtils.ToLowerCamelCase(name); } if (names.Contains(name)) { continue; } if (needComma) { this.WriteComma(); } needComma = true; this.Write(name, ": "); var primitiveExpr = member.Initializer as PrimitiveExpression; if (primitiveExpr != null && primitiveExpr.Value is AstType) { this.Write(Inspector.GetStructDefaultValue((AstType)primitiveExpr.Value, this.Emitter)); } else { member.Initializer.AcceptVisitor(this.Emitter); } } } } } }
protected virtual void EmitCtorForInstantiableClass() { var baseType = this.Emitter.GetBaseTypeDefinition(); var typeDef = this.Emitter.GetTypeDefinition(); var isObjectLiteral = this.Emitter.Validator.IsObjectLiteral(typeDef); var isPlainMode = this.Emitter.Validator.GetObjectCreateMode(typeDef) == 0; var ctorWrappers = isObjectLiteral ? new string[0] : this.EmitInitMembers().ToArray(); if (!this.TypeInfo.HasRealInstantiable(this.Emitter) && ctorWrappers.Length == 0 || isObjectLiteral && isPlainMode) { if (this.ctorHeader) { this.WriteNewLine(); this.EndBlock(); } return; } bool forceDefCtor = isObjectLiteral && this.Emitter.Validator.GetObjectCreateMode(typeDef) == 1 && this.TypeInfo.Ctors.Count == 0; if (typeDef.IsValueType || forceDefCtor || (this.TypeInfo.Ctors.Count == 0 && ctorWrappers.Length > 0)) { this.TypeInfo.Ctors.Add(new ConstructorDeclaration { Modifiers = Modifiers.Public, Body = new BlockStatement() }); } if (!this.ctorHeader && this.TypeInfo.Ctors.Count > 0) { this.EnsureComma(); this.ctorHeader = true; this.Write(JS.Fields.CTORS); this.WriteColon(); this.BeginBlock(); } foreach (var ctor in this.TypeInfo.Ctors) { this.EnsureComma(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(ctor.Parameters, ctor.Body); var ctorName = JS.Funcs.CONSTRUCTOR; if (this.TypeInfo.Ctors.Count > 1 && ctor.Parameters.Count > 0) { var overloads = OverloadsCollection.Create(this.Emitter, ctor); ctorName = overloads.GetOverloadName(); } XmlToJsDoc.EmitComment(this, ctor); this.Write(ctorName); this.WriteColon(); this.WriteFunction(); int pos = this.Emitter.Output.Length; this.EmitMethodParameters(ctor.Parameters, null, ctor); var ctorParams = this.Emitter.Output.ToString().Substring(pos); this.WriteSpace(); this.BeginBlock(); var len = this.Emitter.Output.Length; var requireNewLine = false; var noThisInvocation = ctor.Initializer == null || ctor.Initializer.IsNull || ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base; IWriterInfo oldWriter = null; if (ctorWrappers.Length > 0 && noThisInvocation) { oldWriter = this.SaveWriter(); this.NewWriter(); } this.ConvertParamsToReferences(ctor.Parameters); if (len != this.Emitter.Output.Length) { requireNewLine = true; } if (isObjectLiteral) { if (requireNewLine) { this.WriteNewLine(); } this.Write("var " + JS.Vars.D_THIS + " = "); var isBaseObjectLiteral = baseType != null && this.Emitter.Validator.IsObjectLiteral(baseType); if (isBaseObjectLiteral && baseType != null && (!this.Emitter.Validator.IsExternalType(baseType) || this.Emitter.Validator.IsBridgeClass(baseType)) || (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This)) { this.EmitBaseConstructor(ctor, ctorName, true); } else if (isBaseObjectLiteral && baseType != null && ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { this.EmitExternalBaseCtor(ctor, ref requireNewLine); } else { this.Write("{};"); } this.WriteNewLine(); string name = this.Emitter.Validator.GetCustomTypeName(typeDef, this.Emitter); if (name.IsEmpty()) { name = BridgeTypes.DefinitionToJsName(this.TypeInfo.Type, this.Emitter); } this.Write(JS.Vars.D_THIS + "." + JS.Funcs.GET_TYPE + " = function () { return " + name + "; };"); this.WriteNewLine(); this.Write("(function ()"); this.BeginBlock(); requireNewLine = false; } if (noThisInvocation) { if (requireNewLine) { this.WriteNewLine(); } if (isObjectLiteral) { var fieldBlock = new FieldBlock(this.Emitter, this.TypeInfo, false, false, true); fieldBlock.Emit(); var properties = this.TypeInfo.InstanceProperties; var names = new List <string>(properties.Keys); foreach (var name in names) { var props = properties[name]; foreach (var prop in props) { var p = prop as PropertyDeclaration; if (p != null) { if (p.Getter.Body.IsNull && p.Setter.Body.IsNull) { continue; } this.Write(JS.Types.Object.DEFINEPROPERTY); this.WriteOpenParentheses(); this.Write("this, "); this.WriteScript(OverloadsCollection.Create(this.Emitter, p).GetOverloadName()); this.WriteComma(); this.Emitter.Comma = false; this.BeginBlock(); var memberResult = this.Emitter.Resolver.ResolveNode(p, this.Emitter) as MemberResolveResult; var block = new VisitorPropertyBlock(this.Emitter, p); block.EmitPropertyMethod(p, p.Getter, ((IProperty)memberResult.Member).Getter, false, true); block.EmitPropertyMethod(p, p.Setter, ((IProperty)memberResult.Member).Setter, true, true); this.EnsureComma(true); this.Write(JS.Fields.ENUMERABLE + ": true"); this.WriteNewLine(); this.EndBlock(); this.WriteCloseParentheses(); this.Write(";"); this.WriteNewLine(); } } } } else { this.Write("this." + JS.Funcs.INITIALIZE + "();"); requireNewLine = true; } } if (!isObjectLiteral) { if (baseType != null && (!this.Emitter.Validator.IsExternalType(baseType) || this.Emitter.Validator.IsBridgeClass(baseType)) || (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This)) { if (requireNewLine) { this.WriteNewLine(); requireNewLine = false; } this.EmitBaseConstructor(ctor, ctorName, false); } else if (baseType != null && ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { this.EmitExternalBaseCtor(ctor, ref requireNewLine); } } var script = this.Emitter.GetScript(ctor); if (script == null) { if (ctor.Body.HasChildren) { var beginPosition = this.Emitter.Output.Length; if (requireNewLine) { this.WriteNewLine(); } ctor.Body.AcceptChildren(this.Emitter); if (!this.Emitter.IsAsync) { this.EmitTempVars(beginPosition, true); } } else if (requireNewLine) { this.WriteNewLine(); } } else { if (requireNewLine) { this.WriteNewLine(); } this.WriteLines(script); } if (oldWriter != null) { this.WrapBody(oldWriter, ctorWrappers, ctorParams); } if (isObjectLiteral) { if (requireNewLine) { this.WriteNewLine(); } this.EndBlock(); this.Write(")." + JS.Funcs.CALL + "(" + JS.Vars.D_THIS + ");"); this.WriteNewLine(); this.Write("return " + JS.Vars.D_THIS + ";"); this.WriteNewLine(); } this.EndBlock(); this.Emitter.Comma = true; this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); } if (this.ctorHeader) { this.WriteNewLine(); this.EndBlock(); } }
protected void VisitObjectCreateExpression() { ObjectCreateExpression objectCreateExpression = this.ObjectCreateExpression; int pos = this.Emitter.Output.Length; var resolveResult = this.Emitter.Resolver.ResolveNode(objectCreateExpression.Type, this.Emitter) as TypeResolveResult; bool isTypeParam = resolveResult.Type.Kind == TypeKind.TypeParameter; var type = isTypeParam ? null : this.Emitter.GetTypeDefinition(objectCreateExpression.Type); if (type != null && type.BaseType != null && type.BaseType.FullName == "System.MulticastDelegate") { bool wrap = false; var parent = objectCreateExpression.Parent as InvocationExpression; if (parent != null && parent.Target == objectCreateExpression) { wrap = true; } if (wrap) { this.WriteOpenParentheses(); } objectCreateExpression.Arguments.First().AcceptVisitor(this.Emitter); if (wrap) { this.WriteCloseParentheses(); } return; } var argsInfo = new ArgumentsInfo(this.Emitter, objectCreateExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var argsNames = argsInfo.ArgumentsNames; var paramsArg = argsInfo.ParamsExpression; var argsCount = argsExpressions.Count(); var invocationResolveResult = this.Emitter.Resolver.ResolveNode(objectCreateExpression, this.Emitter) as InvocationResolveResult; string inlineCode = null; if (invocationResolveResult != null) { inlineCode = this.Emitter.GetInline(invocationResolveResult.Member); } var customCtor = isTypeParam ? "" : (this.Emitter.Validator.GetCustomConstructor(type) ?? ""); var hasInitializer = !objectCreateExpression.Initializer.IsNull && objectCreateExpression.Initializer.Elements.Count > 0; bool isCollectionInitializer = false; AstNodeCollection <Expression> elements = null; if (hasInitializer) { elements = objectCreateExpression.Initializer.Elements; isCollectionInitializer = elements.Count > 0 && elements.First() is ArrayInitializerExpression; } if (inlineCode == null && Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success) { this.WriteOpenBrace(); this.WriteSpace(); if (hasInitializer) { this.WriteObjectInitializer(objectCreateExpression.Initializer.Elements, this.Emitter.AssemblyInfo.PreserveMemberCase, type, invocationResolveResult); this.WriteSpace(); } else if (this.Emitter.Validator.IsObjectLiteral(type)) { this.WriteObjectInitializer(null, this.Emitter.AssemblyInfo.PreserveMemberCase, type, invocationResolveResult); this.WriteSpace(); } this.WriteCloseBrace(); } else { if (hasInitializer) { this.Write(Bridge.Translator.Emitter.ROOT); this.WriteDot(); this.Write(Bridge.Translator.Emitter.MERGE_OBJECT); this.WriteOpenParentheses(); } if (inlineCode != null) { new InlineArgumentsBlock(this.Emitter, argsInfo, inlineCode).Emit(); } else { if (String.IsNullOrEmpty(customCtor)) { this.WriteNew(); objectCreateExpression.Type.AcceptVisitor(this.Emitter); } else { this.Write(customCtor); } this.WriteOpenParentheses(); if (!isTypeParam && !this.Emitter.Validator.IsIgnoreType(type) && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType ? 0 : 1)) { this.WriteScript(OverloadsCollection.Create(this.Emitter, ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(objectCreateExpression, this.Emitter)).Member).GetOverloadName()); if (argsExpressions.Length > 0) { this.WriteComma(); } } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); } if (hasInitializer) { this.WriteComma(); bool needComma = false; if (isCollectionInitializer) { this.Write("["); this.WriteNewLine(); this.Indent(); } else { this.BeginBlock(); } foreach (Expression item in elements) { if (needComma) { this.WriteComma(true); } needComma = true; if (item is NamedExpression) { var namedExpression = (NamedExpression)item; new NameBlock(this.Emitter, namedExpression.Name, namedExpression, namedExpression.Expression).Emit(); } else if (item is NamedArgumentExpression) { var namedArgumentExpression = (NamedArgumentExpression)item; new NameBlock(this.Emitter, namedArgumentExpression.Name, namedArgumentExpression, namedArgumentExpression.Expression).Emit(); } else if (item is ArrayInitializerExpression) { var arrayInitializer = (ArrayInitializerExpression)item; this.Write("["); foreach (var el in arrayInitializer.Elements) { this.EnsureComma(false); el.AcceptVisitor(this.Emitter); this.Emitter.Comma = true; } this.Write("]"); this.Emitter.Comma = false; } else if (item is IdentifierExpression) { var identifierExpression = (IdentifierExpression)item; new IdentifierBlock(this.Emitter, identifierExpression).Emit(); } } this.WriteNewLine(); if (isCollectionInitializer) { this.Outdent(); this.Write("]"); } else { this.EndBlock(); } this.WriteSpace(); this.WriteCloseParentheses(); } } //Helpers.CheckValueTypeClone(invocationResolveResult, this.ObjectCreateExpression, this, pos); }
protected virtual void EmitBaseConstructor(ConstructorDeclaration ctor, string ctorName, bool isObjectLiteral) { var initializer = ctor.Initializer != null && !ctor.Initializer.IsNull ? ctor.Initializer : new ConstructorInitializer() { ConstructorInitializerType = ConstructorInitializerType.Base }; bool appendScope = false; if (initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { var baseType = this.Emitter.GetBaseTypeDefinition(); var baseName = JS.Funcs.CONSTRUCTOR; if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } } string name = null; if (this.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } this.Write(name, "."); this.Write(baseName); if (!isObjectLiteral) { this.WriteCall(); appendScope = true; } } else { // this.WriteThis(); string name = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); this.Write(name); this.WriteDot(); var baseName = JS.Funcs.CONSTRUCTOR; var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } this.Write(baseName); if (!isObjectLiteral) { this.WriteCall(); appendScope = true; } } int openPos = this.Emitter.Output.Length; this.WriteOpenParentheses(); if (appendScope) { this.WriteThis(); if (initializer.Arguments.Count > 0) { this.WriteComma(); } } if (initializer.Arguments.Count > 0) { var argsInfo = new ArgumentsInfo(this.Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } this.WriteCloseParentheses(); this.WriteSemiColon(); if (!isObjectLiteral) { this.WriteNewLine(); } }
protected bool ResolveOperator(AssignmentExpression assignmentExpression, OperatorResolveResult orr, int initCount) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, assignmentExpression, orr, method), inline).Emit(); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } return(true); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable.lift("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] { assignmentExpression.Left, assignmentExpression.Right }, null).Emit(); this.WriteCloseParentheses(); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } return(true); } } return(false); }
protected virtual void EmitCtorForInstantiableClass() { this.EmitInitMembers(); if (!this.TypeInfo.HasInstantiable || this.Emitter.Plugins.HasConstructorInjectors(this)) { return; } var baseType = this.Emitter.GetBaseTypeDefinition(); var typeDef = this.Emitter.GetTypeDefinition(); if (typeDef.IsValueType) { this.TypeInfo.Ctors.Add(new ConstructorDeclaration { Modifiers = Modifiers.Public, Body = new BlockStatement() }); } foreach (var ctor in this.TypeInfo.Ctors) { bool skip = false; foreach (var attrSection in ctor.Attributes) { foreach (var attr in attrSection.Attributes) { var rr = this.Emitter.Resolver.ResolveNode(attr.Type, this.Emitter); if (rr.Type.FullName == "Bridge.ExternalAttribute" || rr.Type.FullName == "Bridge.IgnoreAttribute") { skip = true; } } } if (skip) { continue; } this.EnsureComma(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(ctor.Parameters, ctor.Body); var ctorName = "constructor"; if (this.TypeInfo.Ctors.Count > 1 && ctor.Parameters.Count > 0) { var overloads = OverloadsCollection.Create(this.Emitter, ctor); ctorName = overloads.GetOverloadName(); } XmlToJsDoc.EmitComment(this, ctor); this.Write(ctorName); this.WriteColon(); this.WriteFunction(); this.EmitMethodParameters(ctor.Parameters, ctor); this.WriteSpace(); this.BeginBlock(); var requireNewLine = false; if (baseType != null && (!this.Emitter.Validator.IsIgnoreType(baseType) || this.Emitter.Validator.IsBridgeClass(baseType)) || (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This)) { if (requireNewLine) { this.WriteNewLine(); } this.EmitBaseConstructor(ctor, ctorName); requireNewLine = true; } var script = this.Emitter.GetScript(ctor); if (script == null) { if (ctor.Body.HasChildren) { var beginPosition = this.Emitter.Output.Length; if (requireNewLine) { this.WriteNewLine(); } this.ConvertParamsToReferences(ctor.Parameters); ctor.Body.AcceptChildren(this.Emitter); if (!this.Emitter.IsAsync) { this.EmitTempVars(beginPosition, true); } } } else { if (requireNewLine) { this.WriteNewLine(); } foreach (var line in script) { this.Write(line); this.WriteNewLine(); } } this.EndBlock(); this.Emitter.Comma = true; this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); } }
protected override void DoEmit() { IAttribute attribute = this.Attribute; var type = this.Emitter.GetTypeDefinition(attribute.AttributeType); var argsInfo = new ArgumentsInfo(this.Emitter, attribute); string inlineCode = this.Emitter.GetInline(attribute.Constructor); var customCtor = this.Emitter.Validator.GetCustomConstructor(type) ?? ""; var hasInitializer = attribute.NamedArguments.Count > 0; if (inlineCode == null && Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success) { this.WriteOpenBrace(); this.WriteSpace(); if (hasInitializer) { this.WriteObjectInitializer(attribute.NamedArguments, this.Emitter.AssemblyInfo.PreserveMemberCase, type, attribute); this.WriteSpace(); } else if (this.Emitter.Validator.IsObjectLiteral(type)) { this.WriteObjectInitializer(null, this.Emitter.AssemblyInfo.PreserveMemberCase, type, attribute); this.WriteSpace(); } this.WriteCloseBrace(); } else { if (hasInitializer) { this.Write(JS.Funcs.BRIDGE_MERGE); this.WriteOpenParentheses(); } if (inlineCode != null) { new InlineArgumentsBlock(this.Emitter, argsInfo, inlineCode, attribute.Constructor).Emit(); } else { if (String.IsNullOrEmpty(customCtor)) { this.WriteNew(); this.Write(BridgeTypes.ToJsName(attribute.AttributeType, this.Emitter)); } else { this.Write(customCtor); } if (!this.Emitter.Validator.IsExternalType(type) && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType ? 0 : 1)) { this.WriteDot(); var name = OverloadsCollection.Create(this.Emitter, attribute.Constructor).GetOverloadName(); this.Write(name); } this.WriteOpenParentheses(); this.WritePositionalList(attribute.PositionalArguments, attribute); this.WriteCloseParentheses(); } if (hasInitializer) { this.WriteComma(); this.BeginBlock(); var inlineInit = this.WriteObjectInitializer(attribute.NamedArguments, this.Emitter.AssemblyInfo.PreserveMemberCase, type, attribute); this.WriteNewLine(); this.EndBlock(); if (inlineInit.Count > 0) { this.Write(", function () "); this.BeginBlock(); foreach (var init in inlineInit) { this.Write(init); this.WriteNewLine(); } this.EndBlock(); } this.WriteSpace(); this.WriteCloseParentheses(); } } }
protected virtual void EmitBaseConstructor(ConstructorDeclaration ctor, string ctorName) { var initializer = ctor.Initializer != null && !ctor.Initializer.IsNull ? ctor.Initializer : new ConstructorInitializer() { ConstructorInitializerType = ConstructorInitializerType.Base }; bool appendScope = false; if (initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { var baseType = this.Emitter.GetBaseTypeDefinition(); var baseName = "constructor"; if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } } if (baseName == "constructor") { baseName = "$constructor"; } string name = null; if (this.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } this.Write(name, ".prototype."); this.Write(baseName); this.Write(".call"); appendScope = true; } else { // this.WriteThis(); string name = BridgeTypes.ToJsName(this.TypeInfo.Type, this.Emitter); this.Write(name, ".prototype"); this.WriteDot(); var baseName = "constructor"; var member = ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(ctor.Initializer, this.Emitter)).Member; var overloads = OverloadsCollection.Create(this.Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } if (baseName == "constructor") { baseName = "$constructor"; } this.Write(baseName); this.Write(".call"); appendScope = true; } this.WriteOpenParentheses(); if (appendScope) { this.WriteThis(); if (initializer.Arguments.Count > 0) { this.WriteComma(); } } var args = new List <Expression>(initializer.Arguments); for (int i = 0; i < args.Count; i++) { args[i].AcceptVisitor(this.Emitter); if (i != (args.Count - 1)) { this.WriteComma(); } } this.WriteCloseParentheses(); this.WriteSemiColon(); this.WriteNewLine(); }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; int pos = this.Emitter.Output.Length; bool isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; bool isConstTarget = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (targetrr is ConstantResolveResult) { isConstTarget = true; } var memberTargetrr = targetrr as MemberResolveResult; if (memberTargetrr != null && memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField && Helpers.EnumEmitMode(memberTargetrr.Type) == 2) { isConstTarget = true; } if (memberReferenceExpression.Target is ParenthesizedExpression || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Int64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.UInt64)) || (targetrr is ConstantResolveResult && targetrr.Type.IsKnownType(KnownTypeCode.Decimal))) { isConstTarget = false; } var isInvoke = memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression); if (isInvoke) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } else if (expressionResolveResult is MemberResolveResult) { if (((MemberResolveResult)expressionResolveResult).Member is IProperty) { resolveResult = expressionResolveResult; } } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } bool isDynamic = false; if (resolveResult is DynamicInvocationResolveResult) { var dynamicResolveResult = (DynamicInvocationResolveResult)resolveResult; var group = dynamicResolveResult.Target as MethodGroupResolveResult; if (group != null && group.Methods.Count() > 1) { var method = group.Methods.FirstOrDefault(m => { if (dynamicResolveResult.Arguments.Count != m.Parameters.Count) { return(false); } for (int i = 0; i < m.Parameters.Count; i++) { var argType = dynamicResolveResult.Arguments[i].Type; if (argType.Kind == TypeKind.Dynamic) { argType = this.Emitter.Resolver.Compilation.FindType(TypeCode.Object); } if (!m.Parameters[i].Type.Equals(argType)) { return(false); } } return(true); }) ?? group.Methods.Last(); isDynamic = true; resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); resolveResult = new InvocationResolveResult(resolveResult, method, dynamicResolveResult.Arguments); } } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; var globalTarget = member != null?this.Emitter.IsGlobalTarget(member.Member) : null; if (member != null && member.Member.Attributes.Any(a => a.AttributeType.FullName == "Bridge.NonScriptableAttribute")) { throw new EmitterException(this.MemberReferenceExpression, "Member " + member.ToString() + " is marked as not usable from script"); } if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { var interceptor = this.Emitter.Plugins.OnReference(this, this.MemberReferenceExpression, member); if (interceptor.Cancel) { return; } if (!string.IsNullOrEmpty(interceptor.Replacement)) { this.Write(interceptor.Replacement); return; } } if (globalTarget != null && globalTarget.Item1) { var target = globalTarget.Item2; if (!string.IsNullOrWhiteSpace(target)) { bool assign = false; var memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent; var targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression; var assignment = memberExpression as AssignmentExpression; if (assignment != null && assignment.Right == targetExpression) { assign = true; } else { var varInit = memberExpression as VariableInitializer; if (varInit != null && varInit.Initializer == targetExpression) { assign = true; } else if (memberExpression is InvocationExpression) { var targetInvocation = (InvocationExpression)memberExpression; if (targetInvocation.Arguments.Any(a => a == targetExpression)) { assign = true; } } } if (assign) { if (resolveResult is InvocationResolveResult) { this.PushWriter(target); } else { this.Write(target); } return; } } if (resolveResult is InvocationResolveResult) { this.PushWriter(""); } return; } Tuple <bool, bool, string> inlineInfo = member != null ? (isDynamic ? ((Emitter)this.Emitter).GetInlineCodeFromMember(member.Member, null) : this.Emitter.GetInlineCode(memberReferenceExpression)) : null; //string inline = member != null ? this.Emitter.GetInline(member.Member) : null; string inline = inlineInfo != null ? inlineInfo.Item3 : null; if (string.IsNullOrEmpty(inline) && member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var parentInvocation = memberReferenceExpression.Parent as InvocationExpression; if (parentInvocation == null || parentInvocation.Target != memberReferenceExpression) { var method = (IMethod)member.Member; if (method.TypeArguments.Count > 0 || method.IsExtensionMethod) { inline = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } } if (member != null && member.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(member.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inline = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && Helpers.HasThis(inline); inline = hasInline ? Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline; bool isInterfaceMember = false; if (hasInline && inline.StartsWith("<self>")) { hasThis = true; inline = inline.Substring(6); } bool nativeImplementation = true; bool isInterface = inline == null && member != null && member.Member.DeclaringTypeDefinition != null && member.Member.DeclaringTypeDefinition.Kind == TypeKind.Interface; var hasTypeParemeter = isInterface && Helpers.IsTypeParameterType(member.Member.DeclaringType); if (isInterface) { var itypeDef = member.Member.DeclaringTypeDefinition; var variance = MetadataUtils.IsJsGeneric(itypeDef, this.Emitter) && itypeDef.TypeParameters != null && itypeDef.TypeParameters.Any(typeParameter => typeParameter.Variance != VarianceModifier.Invariant); if (variance) { isInterfaceMember = true; } else { var ei = this.Emitter.Validator.IsExternalInterface(itypeDef); if (ei != null) { nativeImplementation = ei.IsNativeImplementation; } else { nativeImplementation = member.Member.DeclaringTypeDefinition.ParentAssembly.AssemblyName == CS.NS.BRIDGE || !this.Emitter.Validator.IsExternalType(member.Member.DeclaringTypeDefinition); } if (ei != null && ei.IsSimpleImplementation) { nativeImplementation = false; isInterfaceMember = false; } else if (ei != null || hasTypeParemeter) { if (hasTypeParemeter || !nativeImplementation) { isInterfaceMember = true; } } } } string interfaceTempVar = null; if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; var oldInline = inline; string thisArg = null; bool isSimple = true; if (this.MemberReferenceExpression.Target is BaseReferenceExpression) { thisArg = "this"; } else { this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } this.WriteSimpleTarget(resolveResult); if (isConstTarget) { this.Write(")"); } thisArg = this.Emitter.Output.ToString(); if (Regex.Matches(inline, @"\{(\*?)this\}").Count > 1) { var mrr = resolveResult as MemberResolveResult; bool isField = mrr != null && mrr.Member is IField && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is LocalResolveResult || mrr.TargetResult is MemberResolveResult && ((MemberResolveResult)mrr.TargetResult).Member is IField); isSimple = (mrr != null && (mrr.TargetResult is ThisResolveResult || mrr.TargetResult is ConstantResolveResult || mrr.TargetResult is LocalResolveResult)) || isField; } } int thisIndex; inline = member != null?Helpers.ConvertTokens(this.Emitter, inline, member.Member) : inline; if (!isSimple) { StringBuilder sb = new StringBuilder(); sb.Append("("); var tempVar = this.GetTempVarName(); inline = inline.Replace("{this}", tempVar); thisIndex = tempVar.Length + 2; sb.Append(tempVar); sb.Append(" = "); sb.Append(thisArg); sb.Append(", "); sb.Append(inline); sb.Append(")"); inline = sb.ToString(); } else { thisIndex = inline.IndexOf("{this}", StringComparison.Ordinal); inline = inline.Replace("{this}", thisArg); } if (member != null && member.Member is IProperty) { this.Emitter.Output = new StringBuilder(); inline = inline.Replace("{0}", "[[0]]"); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); inline = this.Emitter.Output.ToString(); inline = inline.Replace("[[0]]", "{0}"); } else if (member != null && member.Member is IEvent) { this.Emitter.Output = new StringBuilder(); inline = inline.Replace("{0}", "[[0]]"); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); inline = this.Emitter.Output.ToString(); inline = inline.Replace("[[0]]", "{0}"); } this.Emitter.Output = new StringBuilder(inline); Helpers.CheckValueTypeClone(resolveResult, this.MemberReferenceExpression, this, pos); inline = this.Emitter.Output.ToString(); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inline, null, thisArg, range); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), oldInline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (member != null && member.Member is IField && inline.Contains("{0}")) { this.PushWriter(inline, null, thisArg, range); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inline)) { this.PushWriter(inline, null, thisArg, range); } else { this.Write(inline); } } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member)) { var parentExpression = memberReferenceExpression.Parent as MemberReferenceExpression; bool wrap = false; if (parentExpression != null) { var ii = this.Emitter.GetInlineCode(parentExpression); if (string.IsNullOrEmpty(ii.Item3)) { wrap = true; this.WriteOpenParentheses(); } } this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); if (wrap) { this.WriteCloseParentheses(); } } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as ITypeDefinition; if (typeDef != null) { var enumMode = Helpers.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsExternalType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3 && enumMode < 7) { string enumStringName = this.Emitter.GetEntityName(member.Member); this.WriteScript(enumStringName); return; } } } if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); return; } else { if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var parentInvocation = memberReferenceExpression.Parent as InvocationExpression; if (parentInvocation == null || parentInvocation.Target != memberReferenceExpression) { if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_CACHE_BIND); this.WriteOpenParentheses(); if (memberReferenceExpression.Target is BaseReferenceExpression) { this.WriteThis(); } else { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, false); } this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (interfaceTempVar != null) { this.Write(interfaceTempVar); } else { this.WriteSimpleTarget(resolveResult); } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar, member, false); } else { this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation)); } if (!isStatic) { this.Write(")"); } } return; } } bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition))) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } } if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } if (targetVar == null && isInterfaceMember) { interfaceTempVar = this.WriteTarget(resolveResult, isInterfaceMember, memberTargetrr, targetrr, true); } else { this.WriteSimpleTarget(resolveResult); } if (member != null && targetrr != null && targetrr.Type.Kind == TypeKind.Delegate && (member.Member.Name == "Invoke")) { var method = member.Member as IMethod; if (!(method != null && method.IsExtensionMethod)) { return; } } if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } } var targetResolveResult = targetrr as MemberResolveResult; if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null) { if (isRefArg) { this.WriteComma(); } else if (!isInterfaceMember && !this.NoTarget) { this.WriteDot(); } } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (!(resolveResult is InvocationResolveResult) && member != null && member.Member is IMethod) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline, (IMethod)member.Member, targetrr).EmitFunctionReference(); } else if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment) || (member.Member != null && member.Member is IEvent)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && (member.Member.DeclaringTypeDefinition == null || (!this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition) || member.Member.IsStatic))) { if (member.Member is IProperty && targetrr != null && targetrr.Type.GetDefinition() != null && this.Emitter.Validator.IsObjectLiteral(targetrr.Type.GetDefinition()) && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { this.Write(this.Emitter.GetLiteralEntityName(member.Member)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var name = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); var property = (IProperty)member.Member; var proto = member.IsVirtualCall || property.IsVirtual || property.IsOverride; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && !property.IsIndexer && proto) { var alias = BridgeTypes.ToJsName(member.Member.DeclaringType, this.Emitter, isAlias: true); if (alias.StartsWith("\"")) { alias = alias.Insert(1, "$"); name = alias + "+\"$" + name + "\""; this.WriteIdentifier(name, false); } else { name = "$" + alias + "$" + name; this.WriteIdentifier(name); } } else { this.WriteIdentifier(name); } } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(Bridge.Translator.Emitter.ConvertConstant(member.ConstantValue, memberReferenceExpression, this.Emitter)); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var fieldName = OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName(!nativeImplementation); if (isRefArg) { this.WriteScript(fieldName); } else { this.WriteIdentifier(fieldName); } } } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = resolveResult as CSharpInvocationResolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName(!nativeImplementation)); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(!nativeImplementation)); } } else if (member.Member is IEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract, Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); } else { this.Write(Helpers.GetEventRef(member.Member, this.Emitter, this.Emitter.AssignmentType != AssignmentOperatorType.Add, ignoreInterface: !nativeImplementation)); } this.WriteOpenParentheses(); } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { this.Write(this.Emitter.GetEntityName(member.Member)); } } } else { if (isInterfaceMember) { this.WriteInterfaceMember(interfaceTempVar ?? targetVar, member, false); } else { var memberName = this.Emitter.GetEntityName(member.Member); if (isRefArg) { this.WriteScript(memberName); } else { this.WriteIdentifier(memberName); } } } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
protected void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { foreach (var attrSection in methodDeclaration.Attributes) { foreach (var attr in attrSection.Attributes) { var rr = this.Emitter.Resolver.ResolveNode(attr.Type, this.Emitter); if (rr.Type.FullName == "Bridge.ExternalAttribute") { return; } else if (rr.Type.FullName == "Bridge.InitAttribute") { InitPosition initPosition = InitPosition.After; if (attr.HasArgumentList) { if (attr.Arguments.Any()) { var argExpr = attr.Arguments.First(); var argrr = this.Emitter.Resolver.ResolveNode(argExpr, this.Emitter); if (argrr.ConstantValue is int) { initPosition = (InitPosition)argrr.ConstantValue; } } } if (initPosition > 0) { return; } } } } this.EnsureComma(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(methodDeclaration.Parameters, methodDeclaration.Body); var overloads = OverloadsCollection.Create(this.Emitter, methodDeclaration); XmlToJsDoc.EmitComment(this, this.MethodDeclaration); var isEntryPoint = Helpers.IsEntryPointMethod(this.Emitter, this.MethodDeclaration); var member_rr = (MemberResolveResult)this.Emitter.Resolver.ResolveNode(this.MethodDeclaration, this.Emitter); string name = overloads.GetOverloadName(false, null, OverloadsCollection.ExcludeTypeParameterForDefinition(member_rr)); if (isEntryPoint) { this.Write(JS.Funcs.ENTRY_POINT_NAME); } else { this.Write(name); } this.WriteColon(); this.WriteFunction(); if (isEntryPoint) { this.Write(name); this.WriteSpace(); } else { var nm = Helpers.GetFunctionName(this.Emitter.AssemblyInfo.NamedFunctions, member_rr.Member, this.Emitter); if (nm != null) { this.Write(nm); this.WriteSpace(); } } this.EmitMethodParameters(methodDeclaration.Parameters, methodDeclaration.TypeParameters.Count > 0 && Helpers.IsIgnoreGeneric(methodDeclaration, this.Emitter) ? null : methodDeclaration.TypeParameters, methodDeclaration); this.WriteSpace(); var script = this.Emitter.GetScript(methodDeclaration); if (script == null) { if (YieldBlock.HasYield(methodDeclaration.Body)) { new GeneratorBlock(this.Emitter, methodDeclaration).Emit(); } else if (methodDeclaration.HasModifier(Modifiers.Async) || AsyncBlock.HasGoto(methodDeclaration.Body)) { new AsyncBlock(this.Emitter, methodDeclaration).Emit(); } else { methodDeclaration.Body.AcceptVisitor(this.Emitter); } } else { this.BeginBlock(); this.WriteLines(script); this.EndBlock(); } this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); this.Emitter.Comma = true; }
private void HandleDecimal(ResolveResult resolveOperator, bool isLong = false) { var orr = resolveOperator as OperatorResolveResult; var op = this.UnaryOperatorExpression.Operator; var oldType = this.Emitter.UnaryOperatorType; var oldAccessor = this.Emitter.IsUnaryAccessor; var typeCode = isLong ? KnownTypeCode.Int64 : KnownTypeCode.Decimal; this.Emitter.UnaryOperatorType = op; var argResolverResult = this.Emitter.Resolver.ResolveNode(this.UnaryOperatorExpression.Expression, this.Emitter); bool nullable = NullableType.IsNullable(argResolverResult.Type); bool isAccessor = false; var memberArgResolverResult = argResolverResult as MemberResolveResult; if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty) { var isIgnore = this.Emitter.Validator.IsExternalType(memberArgResolverResult.Member.DeclaringTypeDefinition); var inlineAttr = this.Emitter.GetAttribute(memberArgResolverResult.Member.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute"); var ignoreAccessor = this.Emitter.Validator.IsExternalType(((IProperty)memberArgResolverResult.Member).Getter); var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member); isAccessor = ((IProperty)memberArgResolverResult.Member).IsIndexer; if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer) { isAccessor = false; } } else if (argResolverResult is ArrayAccessResolveResult) { isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1; } var isOneOp = op == UnaryOperatorType.Increment || op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostIncrement || op == UnaryOperatorType.PostDecrement; if (isAccessor && isOneOp) { this.Emitter.IsUnaryAccessor = true; if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.Emitter.IsUnaryAccessor = false; this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.Emitter.IsUnaryAccessor = true; this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } this.Emitter.UnaryOperatorType = oldType; this.Emitter.IsUnaryAccessor = oldAccessor; return; } var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (orr != null && method == null) { var name = Helpers.GetUnaryOperatorMethodName(this.UnaryOperatorExpression.Operator); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (orr != null && orr.IsLiftedOperator) { if (!isOneOp) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); } string action = JS.Funcs.Math.LIFT1; string op_name = null; switch (this.UnaryOperatorExpression.Operator) { case UnaryOperatorType.Minus: op_name = JS.Funcs.Math.NEG; break; case UnaryOperatorType.Plus: op_name = "clone"; break; case UnaryOperatorType.BitNot: op_name = "not"; break; case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "(\"" + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "\", "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true); this.Write(")"); this.WriteCloseParentheses(); this.Write(" : null"); break; case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "(\"" + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "\", "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true); this.Write(")"); this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); this.Write(" : null"); break; } if (!isOneOp) { this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit(); this.AddOveflowFlag(typeCode, op_name, true); this.WriteCloseParentheses(); } } else if (method == null) { string op_name = null; var isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement; if (isStatement) { if (op == UnaryOperatorType.PostIncrement) { op = UnaryOperatorType.Increment; } else if (op == UnaryOperatorType.PostDecrement) { op = UnaryOperatorType.Decrement; } } switch (op) { case UnaryOperatorType.Minus: op_name = JS.Funcs.Math.NEG; break; case UnaryOperatorType.Plus: op_name = "clone"; break; case UnaryOperatorType.BitNot: op_name = "not"; break; case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: if (!isStatement) { this.WriteOpenParentheses(); } this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("." + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "("); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false); this.Write(")"); if (!isStatement) { this.WriteCloseParentheses(); } break; case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("." + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "("); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false); this.Write("), "); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); break; } if (!isOneOp) { this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.AddOveflowFlag(typeCode, op_name, false); this.WriteCloseParentheses(); } } else { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { if (isOneOp) { var isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement; if (isStatement || this.UnaryOperatorExpression.Operator == UnaryOperatorType.Increment || this.UnaryOperatorExpression.Operator == UnaryOperatorType.Decrement) { if (!isStatement) { this.WriteOpenParentheses(); } this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit (); if (!isStatement) { this.WriteCloseParentheses(); } } else { this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit(); this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); } } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit(); } } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit(); this.WriteCloseParentheses(); } } this.Emitter.UnaryOperatorType = oldType; }
private void WriteInterfaceMember(string interfaceTempVar, MemberResolveResult resolveResult, bool isSetter, string prefix = null) { var externalInterface = this.Emitter.Validator.IsExternalInterface(resolveResult.Member.DeclaringTypeDefinition); if (interfaceTempVar != null && externalInterface == null) { this.WriteComma(); this.Write(interfaceTempVar); } if (externalInterface != null && externalInterface.IsDualImplementation) { if (interfaceTempVar != null) { this.WriteCloseParentheses(); } this.WriteOpenBracket(); this.Write(JS.Funcs.BRIDGE_GET_I); this.WriteOpenParentheses(); if (interfaceTempVar != null) { this.Write(interfaceTempVar); } else { this.WriteSimpleTarget(resolveResult); } this.WriteComma(); var interfaceName = OverloadsCollection.Create(Emitter, resolveResult.Member, isSetter).GetOverloadName(false, prefix); if (interfaceName.StartsWith("\"")) { this.Write(interfaceName); } else { this.WriteScript(interfaceName); } this.WriteComma(); this.WriteScript(OverloadsCollection.Create(Emitter, resolveResult.Member, isSetter).GetOverloadName(true, prefix)); this.Write(")"); this.WriteCloseBracket(); return; } this.WriteOpenBracket(); this.Write(OverloadsCollection.Create(Emitter, resolveResult.Member, isSetter).GetOverloadName(externalInterface != null && externalInterface.IsSimpleImplementation, prefix)); this.WriteCloseBracket(); if (interfaceTempVar != null) { this.WriteCloseParentheses(); } }
private void HandleType(ResolveResult resolveOperator, KnownTypeCode typeCode, string op_name, string action) { var orr = resolveOperator as OperatorResolveResult; var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(this.BinaryOperatorExpression.Operator); var type = this.Emitter.Resolver.Compilation.FindType(typeCode); method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = this.Emitter.GetInline(method); if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.BinaryOperatorExpression.Left, this.BinaryOperatorExpression.Right }, null, null, 0) .Emit(); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.BinaryOperatorExpression, orr, method), inline).Emit(); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, new Expression[] { this.BinaryOperatorExpression.Left, this.BinaryOperatorExpression.Right }, null, null, 0) .Emit(); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } } else { if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.BinaryOperatorExpression.Left, this.BinaryOperatorExpression.Right }, null, null, 0) .Emit(); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else { this.BinaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.BinaryOperatorExpression.Right.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } } }
protected bool EmitMemberAlias(IMember member, IMember interfaceMember) { bool nonEmpty = false; if (member.IsShadowing || !member.IsOverride) { var baseMember = InheritanceHelper.GetBaseMember(member); if (baseMember != null && baseMember.ImplementedInterfaceMembers.Contains(interfaceMember)) { return(false); } } if (member is IProperty) { var property = (IProperty)member; if (property.CanGet) { nonEmpty = true; this.EnsureComma(); this.WriteScript(Helpers.GetPropertyRef(member, this.Emitter, false, false, false, true)); this.WriteComma(); var alias = Helpers.GetPropertyRef(interfaceMember, this.Emitter, false, false, false); if (alias.StartsWith("\"")) { this.Write(alias); } else { this.WriteScript(alias); } this.Emitter.Comma = true; } if (property.CanSet) { nonEmpty = true; this.EnsureComma(); this.WriteScript(Helpers.GetPropertyRef(member, this.Emitter, true, false, false, true)); this.WriteComma(); var alias = Helpers.GetPropertyRef(interfaceMember, this.Emitter, true, false, false); if (alias.StartsWith("\"")) { this.Write(alias); } else { this.WriteScript(alias); } this.Emitter.Comma = true; } } else if (member is IEvent) { var ev = (IEvent)member; if (ev.CanAdd) { nonEmpty = true; this.EnsureComma(); this.WriteScript(Helpers.GetEventRef(member, this.Emitter, false, false, false, true)); this.WriteComma(); var alias = Helpers.GetEventRef(interfaceMember, this.Emitter, false, false, false); if (alias.StartsWith("\"")) { this.Write(alias); } else { this.WriteScript(alias); } this.Emitter.Comma = true; } if (ev.CanRemove) { nonEmpty = true; this.EnsureComma(); this.WriteScript(Helpers.GetEventRef(member, this.Emitter, true, false, false, true)); this.WriteComma(); var alias = Helpers.GetEventRef(interfaceMember, this.Emitter, true, false, false); if (alias.StartsWith("\"")) { this.Write(alias); } else { this.WriteScript(alias); } this.Emitter.Comma = true; } } else { nonEmpty = true; this.EnsureComma(); this.WriteScript(OverloadsCollection.Create(Emitter, member).GetOverloadName(false, null, true)); this.WriteComma(); var alias = OverloadsCollection.Create(Emitter, interfaceMember).GetOverloadName(); if (alias.StartsWith("\"")) { this.Write(alias); } else { this.WriteScript(alias); } } this.Emitter.Comma = true; return(nonEmpty); }
protected bool EmitMemberAlias(IMember member, IMember interfaceMember) { bool nonEmpty = false; if (member.IsShadowing || !member.IsOverride) { var baseMember = InheritanceHelper.GetBaseMember(member); if (baseMember != null && baseMember.ImplementedInterfaceMembers.Contains(interfaceMember)) { return(false); } } var excludeTypeParam = OverloadsCollection.ExcludeTypeParameterForDefinition(member); var excludeAliasTypeParam = member.IsExplicitInterfaceImplementation && !excludeTypeParam; var pair = false; var itypeDef = interfaceMember.DeclaringTypeDefinition; if (!member.IsExplicitInterfaceImplementation && MetadataUtils.IsJsGeneric(itypeDef, Emitter) && itypeDef.TypeParameters != null && itypeDef.TypeParameters.Any(typeParameter => typeParameter.Variance != VarianceModifier.Invariant)) { pair = true; } if (member is IProperty && ((IProperty)member).IsIndexer) { var property = (IProperty)member; if (property.CanGet) { nonEmpty = true; EnsureComma(); WriteScript(Helpers.GetPropertyRef(member, Emitter, false, false, false, excludeTypeParam)); WriteComma(); var alias = Helpers.GetPropertyRef(interfaceMember, Emitter, false, false, false, withoutTypeParams: excludeAliasTypeParam); if (pair) { WriteOpenBracket(); } if (alias.StartsWith("\"")) { Write(alias); } else { WriteScript(alias); } if (pair) { WriteComma(); WriteScript(Helpers.GetPropertyRef(interfaceMember, Emitter, withoutTypeParams: true)); WriteCloseBracket(); } Emitter.Comma = true; } if (property.CanSet) { nonEmpty = true; EnsureComma(); WriteScript(Helpers.GetPropertyRef(member, Emitter, true, false, false, excludeTypeParam)); WriteComma(); var alias = Helpers.GetPropertyRef(interfaceMember, Emitter, true, false, false, withoutTypeParams: excludeAliasTypeParam); if (pair) { WriteOpenBracket(); } if (alias.StartsWith("\"")) { Write(alias); } else { WriteScript(alias); } if (pair) { WriteComma(); WriteScript(Helpers.GetPropertyRef(interfaceMember, Emitter, true, withoutTypeParams: true)); WriteCloseBracket(); } Emitter.Comma = true; } } else if (member is IEvent ev) { if (ev.CanAdd) { nonEmpty = true; EnsureComma(); WriteScript(Helpers.GetEventRef(member, Emitter, false, false, false, excludeTypeParam)); WriteComma(); var alias = Helpers.GetEventRef(interfaceMember, Emitter, false, false, false, excludeAliasTypeParam); if (pair) { WriteOpenBracket(); } if (alias.StartsWith("\"")) { Write(alias); } else { WriteScript(alias); } if (pair) { WriteComma(); WriteScript(Helpers.GetEventRef(interfaceMember, Emitter, withoutTypeParams: true)); WriteCloseBracket(); } Emitter.Comma = true; } if (ev.CanRemove) { nonEmpty = true; EnsureComma(); WriteScript(Helpers.GetEventRef(member, Emitter, true, false, false, excludeTypeParam)); WriteComma(); var alias = Helpers.GetEventRef(interfaceMember, Emitter, true, false, false, excludeAliasTypeParam); if (pair) { WriteOpenBracket(); } if (alias.StartsWith("\"")) { Write(alias); } else { WriteScript(alias); } if (pair) { WriteComma(); WriteScript(Helpers.GetEventRef(interfaceMember, Emitter, true, withoutTypeParams: true)); WriteCloseBracket(); } Emitter.Comma = true; } } else { nonEmpty = true; EnsureComma(); WriteScript(OverloadsCollection.Create(Emitter, member).GetOverloadName(false, null, excludeTypeOnly: excludeTypeParam)); WriteComma(); var alias = OverloadsCollection.Create(Emitter, interfaceMember).GetOverloadName(withoutTypeParams: excludeAliasTypeParam); if (pair) { WriteOpenBracket(); } if (alias.StartsWith("\"")) { Write(alias); } else { WriteScript(alias); } if (pair) { WriteComma(); WriteScript(OverloadsCollection.Create(Emitter, interfaceMember).GetOverloadName(withoutTypeParams: true)); WriteCloseBracket(); } } Emitter.Comma = true; return(nonEmpty); }
public static int CheckConversion(ConversionBlock block, Expression expression) { try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); var conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); int level = 0; if (block.Emitter.IsAssignment) { return(level); } /*if (expression is ParenthesizedExpression && expression.Parent is CastExpression) * { * return level; * }*/ if (conversion.IsUserDefined && expression.Parent is CastExpression && ((CastExpression)expression.Parent).Expression == expression) { var parentConversion = block.Emitter.Resolver.Resolver.GetConversion((CastExpression)expression.Parent); if (!parentConversion.IsUserDefined || parentConversion.Method.Equals(conversion.Method)) { return(level); } } if (rr is ConstantResolveResult && expression is CastExpression && !conversion.IsUserDefined) { return(level); } var convrr = rr as ConversionResolveResult; if (convrr != null && convrr.Input is ConstantResolveResult && !convrr.Conversion.IsUserDefined) { return(level); } if (convrr != null && !conversion.IsUserDefined) { conversion = convrr.Conversion; rr = convrr.Input; expectedType = convrr.Type; } if (!((expression.Parent is CastExpression) && !(expression is CastExpression))) { CheckNumericConversion(block, expression, rr, expectedType, conversion); } if (!(conversion.IsExplicit && conversion.IsNumericConversion)) { level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? (level + 1) : level; } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { return(level); } if (!(conversion.IsExplicit && conversion.IsNumericConversion)) { level = ConversionBlock.CheckLongConversion(block, expression, rr, expectedType, conversion) ? (level + 1) : level; } if (Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { return(level); } if (conversion == null) { return(level); } if (conversion.IsIdentityConversion) { return(level); } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return(level); } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.Is64Type(expectedType, block.Emitter.Resolver) && !NullableType.IsNullable(expectedType); if (isLifted) { level++; block.Write("Bridge.Nullable.getValue("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return(level); } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (ObjectCreateExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return(level); } else { if (method.DeclaringTypeDefinition != null && (block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition) || Helpers.IsIgnoreCast(method.DeclaringTypeDefinition, block.Emitter))) { // Still returns true if Nullable.lift( was written. return(level); } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (isLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); level++; } var arg = method.Parameters[0]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(level); } block.WriteOpenParentheses(); level++; } if (Helpers.Is64Type(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.Is64Type(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { var isUint = Helpers.IsULongType(arg.Type, block.Emitter.Resolver, arg.IsParams); block.Write("Bridge." + (isUint ? "ULong" : "Long")); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } if (expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression) { return(level); } block.WriteOpenParentheses(); level++; } return(level); } // Still returns true if Nullable.lift( was written. return(level); } catch { } return(0); }