protected virtual void EmitPropertyMethod(CustomEventDeclaration customEventDeclaration, Accessor accessor, bool remover) { if (!accessor.IsNull && Emitter.GetInline(accessor) == null) { EnsureComma(); ResetLocals(); var prevMap = BuildLocalsMap(); var prevNamesMap = BuildLocalsNamesMap(); AddLocals(new ParameterDeclaration[] { new ParameterDeclaration { Name = "value" } }, accessor.Body); XmlToJsDoc.EmitComment(this, CustomEventDeclaration); var member_rr = (MemberResolveResult)Emitter.Resolver.ResolveNode(customEventDeclaration); Write(Helpers.GetEventRef(customEventDeclaration, Emitter, remover, false, false, OverloadsCollection.ExcludeTypeParameterForDefinition(member_rr))); WriteColon(); WriteFunction(); var m_rr = (MemberResolveResult)Emitter.Resolver.ResolveNode(customEventDeclaration); var nm = Helpers.GetFunctionName(Emitter.AssemblyInfo.NamedFunctions, m_rr.Member, Emitter, remover); if (nm != null) { Write(nm); } WriteOpenParentheses(); Write("value"); WriteCloseParentheses(); WriteSpace(); var script = Emitter.GetScript(accessor); if (script == null) { accessor.Body.AcceptVisitor(Emitter); } else { BeginBlock(); WriteLines(script); EndBlock(); } ClearLocalsMap(prevMap); ClearLocalsNamesMap(prevNamesMap); Emitter.Comma = true; } }
protected bool ResolveOperator(UnaryOperatorExpression unaryOperatorExpression, OperatorResolveResult orr) { if (orr != null && orr.UserDefinedOperatorMethod != null) { var method = orr.UserDefinedOperatorMethod; var inline = Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, unaryOperatorExpression, orr, method), inline).Emit(); return(true); } else { if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT + "("); } Write(H5Types.ToJsName(method.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { WriteComma(); } else { WriteOpenParentheses(); } new ExpressionListBlock(Emitter, new Expression[] { unaryOperatorExpression.Expression }, null, null, 0).Emit(); WriteCloseParentheses(); return(true); } } return(false); }
protected bool IsUserOperator(OperatorResolveResult orr) { var method = orr?.UserDefinedOperatorMethod; if (method != null) { var inline = Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { return(true); } else if (!Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { return(true); } } return(false); }
public IMethod GetCastMethod(IType fromType, IType toType, out string template) { string inline = null; var method = fromType.GetMethods().FirstOrDefault(m => { if (m.IsOperator && (m.Name == "op_Explicit" || m.Name == "op_Implicit") && m.Parameters.Count == 1 && m.ReturnType.ReflectionName == toType.ReflectionName && m.Parameters[0].Type.ReflectionName == fromType.ReflectionName ) { inline = Emitter.GetInline(m); return(true); } return(false); }); if (method == null) { method = toType.GetMethods().FirstOrDefault(m => { if (m.IsOperator && (m.Name == "op_Explicit" || m.Name == "op_Implicit") && m.Parameters.Count == 1 && m.ReturnType.ReflectionName == toType.ReflectionName && (m.Parameters[0].Type.ReflectionName == fromType.ReflectionName) ) { inline = Emitter.GetInline(m); return(true); } return(false); }); } template = inline; return(method); }
private void HandleType(ResolveResult resolveOperator, string variable, string op_name, KnownTypeCode typeCode) { if (AssignmentExpression.Operator == AssignmentOperatorType.Assign) { if (variable != null) { Write(variable); } else { new ExpressionListBlock(Emitter, new Expression[] { AssignmentExpression.Right }, null, null, 0).Emit(); } return; } var orr = resolveOperator as OperatorResolveResult; var method = orr?.UserDefinedOperatorMethod; var assigmentType = Helpers.TypeOfAssignment(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 = Emitter.GetInline(method); if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; Write(action); WriteOpenParentheses(); WriteScript(op_name); WriteComma(); if (variable != null) { new ExpressionListBlock(Emitter, new Expression[] { AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(Emitter, new Expression[] { AssignmentExpression.Left, AssignmentExpression.Right }, null, null, 0).Emit(); } AddOveflowFlag(typeCode, op_name); WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, AssignmentExpression, orr, method), inline).Emit(); } else if (!Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { Write(H5Types.ToJsName(method.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, method).GetOverloadName()); WriteOpenParentheses(); if (variable != null) { new ExpressionListBlock(Emitter, new Expression[] { AssignmentExpression.Left }, null, null, 0).Emit(); Write(", " + variable); } else { new ExpressionListBlock(Emitter, new Expression[] { AssignmentExpression.Left, AssignmentExpression.Right }, null, null, 0).Emit(); } WriteCloseParentheses(); } } else { if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; Write(action); WriteOpenParentheses(); WriteScript(op_name); WriteComma(); if (variable != null) { new ExpressionListBlock(Emitter, new Expression[] { AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(Emitter, new Expression[] { AssignmentExpression.Left, AssignmentExpression.Right }, null, null, 0).Emit(); } AddOveflowFlag(typeCode, op_name); WriteCloseParentheses(); } else { AssignmentExpression.Left.AcceptVisitor(Emitter); WriteDot(); Write(op_name); WriteOpenParentheses(); AssignmentExpression.Right.AcceptVisitor(Emitter); AddOveflowFlag(typeCode, op_name); WriteCloseParentheses(); } } }
protected bool ResolveOperator(AssignmentExpression assignmentExpression, OperatorResolveResult orr, int initCount, bool thisAssignment) { var method = orr?.UserDefinedOperatorMethod; if (method != null) { var inline = Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { if (Emitter.Writers.Count == initCount && !thisAssignment) { Write("= "); } new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, assignmentExpression, orr, method), inline).Emit(); if (Emitter.Writers.Count > initCount) { PopWriter(); } return(true); } else if (!Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { if (Emitter.Writers.Count == initCount && !thisAssignment) { Write("= "); } if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT + ".("); } Write(H5Types.ToJsName(method.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { WriteComma(); } else { WriteOpenParentheses(); } new ExpressionListBlock(Emitter, new Expression[] { assignmentExpression.Left, assignmentExpression.Right }, null, null, 0).Emit(); WriteCloseParentheses(); if (Emitter.Writers.Count > initCount) { PopWriter(); } return(true); } } return(false); }
protected void VisitAssignmentExpression() { AssignmentExpression assignmentExpression = AssignmentExpression; var oldAssigment = Emitter.IsAssignment; var oldAssigmentType = Emitter.AssignmentType; string variable = null; bool needReturnValue = !(assignmentExpression.Parent is ExpressionStatement); if (needReturnValue && assignmentExpression.Parent is LambdaExpression) { if (Emitter.Resolver.ResolveNode(assignmentExpression.Parent) is LambdaResolveResult lambdarr && lambdarr.ReturnType.Kind == TypeKind.Void) { needReturnValue = false; } } var delegateAssigment = false; bool isEvent = false; var initCount = Emitter.Writers.Count; var asyncExpressionHandling = Emitter.AsyncExpressionHandling; WriteAwaiters(assignmentExpression.Left); WriteAwaiters(assignmentExpression.Right); var leftResolverResult = Emitter.Resolver.ResolveNode(assignmentExpression.Left); var rightResolverResult = Emitter.Resolver.ResolveNode(assignmentExpression.Right); var rr = Emitter.Resolver.ResolveNode(assignmentExpression); var orr = rr as OperatorResolveResult; bool isDecimal = Helpers.IsDecimalType(rr.Type, Emitter.Resolver); bool isLong = Helpers.Is64Type(rr.Type, Emitter.Resolver); var expectedType = Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, Emitter.Resolver); bool isUserOperator = IsUserOperator(orr); var rrType = rr.Type; if (rrType.Kind == TypeKind.Enum) { rrType = rrType.GetDefinition().EnumUnderlyingType; } bool isUint = rrType.IsKnownType(KnownTypeCode.UInt16) || rrType.IsKnownType(KnownTypeCode.UInt32) || rrType.IsKnownType(KnownTypeCode.UInt64); if (!isLong && rr.Type.Kind == TypeKind.Enum && Helpers.Is64Type(rr.Type.GetDefinition().EnumUnderlyingType, Emitter.Resolver)) { isLong = true; } if (!isLongExpected && expectedType.Kind == TypeKind.Enum && Helpers.Is64Type(expectedType.GetDefinition().EnumUnderlyingType, Emitter.Resolver)) { isLongExpected = true; } var charToString = -1; if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { if (orr.Operands[i] is ConversionResolveResult crr && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } var memberTargetrr = leftResolverResult as MemberResolveResult; bool isField = (memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult)) || leftResolverResult is ThisResolveResult || leftResolverResult is LocalResolveResult || leftResolverResult is ConstantResolveResult; var rightMemberTargetrr = rightResolverResult as MemberResolveResult; bool isRightSimple = (rightMemberTargetrr != null && rightMemberTargetrr.Member is IField && (rightMemberTargetrr.TargetResult is ThisResolveResult || rightMemberTargetrr.TargetResult is LocalResolveResult)) || rightResolverResult is ThisResolveResult || rightResolverResult is LocalResolveResult || rightResolverResult is ConstantResolveResult; var needTempVar = needReturnValue && (!isRightSimple && !isField || assignmentExpression.Operator != AssignmentOperatorType.Assign); /*if (assignmentExpression.Operator == AssignmentOperatorType.Any) * { * needTempVar = false; * }*/ if (needReturnValue) { if (needTempVar) { variable = GetTempVarName(); Write("(" + variable + " = "); var oldValue1 = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(Emitter); Emitter.ReplaceAwaiterByVar = oldValue1; Write(", "); } else { Write("("); } } if (assignmentExpression.Operator == AssignmentOperatorType.Divide && Emitter.Rules.Integer == IntegerRule.Managed && !(Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(Emitter, assignmentExpression)) && !isLong && !isLongExpected && ( (Helpers.IsIntegerType(leftResolverResult.Type, Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, Emitter.Resolver)) || (Helpers.IsIntegerType(Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), Emitter.Resolver) && Helpers.IsIntegerType(Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), Emitter.Resolver)) )) { Emitter.IsAssignment = true; Emitter.AssignmentType = AssignmentOperatorType.Assign; var oldValue1 = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (Emitter.Writers.Count == initCount) { Write(" = "); } Emitter.ReplaceAwaiterByVar = oldValue1; Emitter.AssignmentType = oldAssigmentType; Emitter.IsAssignment = oldAssigment; Write(JS.Types.H5_INT + "." + JS.Funcs.Math.DIV + "("); assignmentExpression.Left.AcceptVisitor(Emitter); Write(", "); oldValue1 = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(Emitter); Write(")"); Emitter.ReplaceAwaiterByVar = oldValue1; Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (Emitter.Writers.Count > initCount) { PopWriter(); } if (needReturnValue && !isField) { if (needTempVar) { Write(", " + variable); } else { Write(", "); Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(Emitter); Emitter.IsAssignment = oldAssigment; } } if (needReturnValue) { Write(")"); } return; } if (assignmentExpression.Operator == AssignmentOperatorType.Multiply && Emitter.Rules.Integer == IntegerRule.Managed && !(Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(Emitter, assignmentExpression)) && !isLong && !isLongExpected && ( (Helpers.IsInteger32Type(leftResolverResult.Type, Emitter.Resolver) && Helpers.IsInteger32Type(rightResolverResult.Type, Emitter.Resolver) && Helpers.IsInteger32Type(rr.Type, Emitter.Resolver)) || (Helpers.IsInteger32Type(Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), Emitter.Resolver) && Helpers.IsInteger32Type(Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), Emitter.Resolver) && Helpers.IsInteger32Type(rr.Type, Emitter.Resolver)) )) { Emitter.IsAssignment = true; Emitter.AssignmentType = AssignmentOperatorType.Assign; var oldValue1 = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (Emitter.Writers.Count == initCount) { Write(" = "); } Emitter.ReplaceAwaiterByVar = oldValue1; Emitter.AssignmentType = oldAssigmentType; Emitter.IsAssignment = oldAssigment; isUint = NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.UInt32); Write(JS.Types.H5_INT + "." + (isUint ? JS.Funcs.Math.UMUL : JS.Funcs.Math.MUL) + "("); assignmentExpression.Left.AcceptVisitor(Emitter); Write(", "); oldValue1 = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(Emitter); if (IsInCheckedContext(Emitter, assignmentExpression)) { Write(", 1"); } Write(")"); Emitter.ReplaceAwaiterByVar = oldValue1; Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (Emitter.Writers.Count > initCount) { PopWriter(); } if (needReturnValue && !isField) { if (needTempVar) { Write(", " + variable); } else { Write(", "); Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(Emitter); Emitter.IsAssignment = oldAssigment; } } if (needReturnValue) { Write(")"); } return; } bool templateDelegateAssigment = false; if (assignmentExpression.Operator == AssignmentOperatorType.Add || assignmentExpression.Operator == AssignmentOperatorType.Subtract) { var add = assignmentExpression.Operator == AssignmentOperatorType.Add; if (Emitter.Validator.IsDelegateOrLambda(leftResolverResult)) { delegateAssigment = true; if (leftResolverResult is MemberResolveResult leftMemberResolveResult) { isEvent = leftMemberResolveResult.Member is IEvent; Emitter.IsAssignment = true; Emitter.AssignmentType = assignmentExpression.Operator; templateDelegateAssigment = !string.IsNullOrWhiteSpace(Emitter.GetInline(leftMemberResolveResult.Member)); Emitter.IsAssignment = false; } if (!isEvent) { Emitter.IsAssignment = true; Emitter.AssignmentType = AssignmentOperatorType.Assign; AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); Emitter.IsAssignment = false; if (Emitter.Writers.Count == initCount) { Write(" = "); } Write(add ? JS.Funcs.H5_COMBINE : JS.Funcs.H5_REMOVE); WriteOpenParentheses(); } } } bool nullable = orr != null && orr.IsLiftedOperator; string root = JS.Types.SYSTEM_NULLABLE + "."; bool special = nullable; Emitter.IsAssignment = true; Emitter.AssignmentType = assignmentExpression.Operator; var oldValue = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; bool thisAssignment = leftResolverResult is ThisResolveResult; if (!thisAssignment) { if (special || (isDecimal && isDecimalExpected) || (isLong && isLongExpected) || isUserOperator) { Emitter.AssignmentType = AssignmentOperatorType.Assign; } if (delegateAssigment && !isEvent) { Emitter.IsAssignment = false; } AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (delegateAssigment) { Emitter.IsAssignment = true; } } else { Write("("); } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AssignmentType = oldAssigmentType; Emitter.IsAssignment = oldAssigment; if (Emitter.Writers.Count == initCount && !delegateAssigment && !thisAssignment) { WriteSpace(); } if (isDecimal && isDecimalExpected) { if (Emitter.Writers.Count == initCount) { Write("= "); } oldValue = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; HandleDecimal(rr, variable); if (Emitter.Writers.Count > initCount) { PopWriter(); } if (needTempVar) { Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { Write(", "); Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(Emitter); Emitter.IsAssignment = oldAssigment; } Write(")"); } Emitter.ReplaceAwaiterByVar = oldValue; return; } if (isLong && isLongExpected) { if (Emitter.Writers.Count == initCount) { Write("= "); } oldValue = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; HandleLong(rr, variable, isUint); if (Emitter.Writers.Count > initCount) { PopWriter(); } if (needTempVar) { Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { Write(", "); Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(Emitter); Emitter.IsAssignment = oldAssigment; } Write(")"); } Emitter.ReplaceAwaiterByVar = oldValue; return; } if (ResolveOperator(assignmentExpression, orr, initCount, thisAssignment)) { if (thisAssignment) { Write(")." + JS.Funcs.CLONE + "(this)"); } else if (needReturnValue) { Write(")"); } return; } bool isBool = NullableType.IsNullable(rr.Type) ? NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.Boolean) : rr.Type.IsKnownType(KnownTypeCode.Boolean); if (!delegateAssigment) { if (!special) { switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: Write("+"); break; case AssignmentOperatorType.BitwiseAnd: if (!isBool) { Write("&"); } break; case AssignmentOperatorType.BitwiseOr: if (!isBool) { Write("|"); } break; case AssignmentOperatorType.Divide: Write("/"); break; case AssignmentOperatorType.ExclusiveOr: if (!isBool) { Write("^"); } break; case AssignmentOperatorType.Modulus: Write("%"); break; case AssignmentOperatorType.Multiply: Write("*"); break; case AssignmentOperatorType.ShiftLeft: Write("<<"); break; case AssignmentOperatorType.ShiftRight: Write(isUint ? ">>>" : ">>"); break; case AssignmentOperatorType.Subtract: Write("-"); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } } if (special) { if (Emitter.Writers.Count == initCount) { Write("= "); } Write(root); switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: Write(JS.Funcs.Math.ADD); break; case AssignmentOperatorType.BitwiseAnd: Write(isBool ? JS.Funcs.Math.AND : JS.Funcs.Math.BAND); break; case AssignmentOperatorType.BitwiseOr: Write(isBool ? JS.Funcs.Math.OR : JS.Funcs.Math.BOR); break; case AssignmentOperatorType.Divide: Write(JS.Funcs.Math.DIV); break; case AssignmentOperatorType.ExclusiveOr: Write(JS.Funcs.Math.XOR); break; case AssignmentOperatorType.Modulus: Write(JS.Funcs.Math.MOD); break; case AssignmentOperatorType.Multiply: Write(JS.Funcs.Math.MUL); break; case AssignmentOperatorType.ShiftLeft: Write(JS.Funcs.Math.SL); break; case AssignmentOperatorType.ShiftRight: Write(isUint ? JS.Funcs.Math.SRR : JS.Funcs.Math.SR); break; case AssignmentOperatorType.Subtract: Write(JS.Funcs.Math.SUB); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } WriteOpenParentheses(); assignmentExpression.Left.AcceptVisitor(Emitter); Write(", "); } if (Emitter.Writers.Count == initCount && !thisAssignment && !special) { Write("= "); } } else if (!isEvent) { WriteComma(); } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr || assignmentExpression.Operator == AssignmentOperatorType.ExclusiveOr)) { if (assignmentExpression.Operator != AssignmentOperatorType.ExclusiveOr) { Write("!!("); } assignmentExpression.Left.AcceptVisitor(Emitter); string op = null; switch (assignmentExpression.Operator) { case AssignmentOperatorType.BitwiseAnd: op = " & "; break; case AssignmentOperatorType.BitwiseOr: op = " | "; break; case AssignmentOperatorType.ExclusiveOr: op = " != "; break; } Write(op); } oldValue = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; if (charToString == 1) { Write(JS.Funcs.STRING_FROMCHARCODE + "("); } if (needTempVar) { int pos = Emitter.Output.Length; Write(variable); Helpers.CheckValueTypeClone(rr, assignmentExpression.Right, this, pos); } else { var wrap = assignmentExpression.Operator != AssignmentOperatorType.Assign && Emitter.Writers.Count > initCount && !AssigmentExpressionHelper.CheckIsRightAssigmentExpression(assignmentExpression); if (wrap) { WriteOpenParentheses(); } assignmentExpression.Right.AcceptVisitor(Emitter); if (wrap) { WriteCloseParentheses(); } } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr)) { WriteCloseParentheses(); } if (charToString == 1) { WriteCloseParentheses(); } if (special) { WriteCloseParentheses(); } if (thisAssignment) { Write(")." + JS.Funcs.CLONE + "(this)"); } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (Emitter.Writers.Count > initCount) { var writerCount = Emitter.Writers.Count; for (int i = initCount; i < writerCount; i++) { PopWriter(); } } if (delegateAssigment && !templateDelegateAssigment) { WriteCloseParentheses(); } if (needTempVar) { Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { Write(", "); Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(Emitter); Emitter.IsAssignment = oldAssigment; } Write(")"); } }
private void HandleType(ResolveResult resolveOperator, KnownTypeCode typeCode, string op_name, string action) { var orr = resolveOperator as OperatorResolveResult; var method = orr?.UserDefinedOperatorMethod; if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(BinaryOperatorExpression.Operator); var type = Emitter.Resolver.Compilation.FindType(typeCode); method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = Emitter.GetInline(method); if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "."); Write(action); WriteOpenParentheses(); WriteScript(op_name); WriteComma(); new ExpressionListBlock(Emitter, new Expression[] { BinaryOperatorExpression.Left, BinaryOperatorExpression.Right }, null, null, 0) .Emit(); AddOveflowFlag(typeCode, op_name); WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, BinaryOperatorExpression, orr, method), inline).Emit(); } else if (!Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { Write(H5Types.ToJsName(method.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, method).GetOverloadName()); WriteOpenParentheses(); new ExpressionListBlock(Emitter, new Expression[] { BinaryOperatorExpression.Left, BinaryOperatorExpression.Right }, null, null, 0) .Emit(); AddOveflowFlag(typeCode, op_name); WriteCloseParentheses(); } } else { if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "."); Write(action); WriteOpenParentheses(); WriteScript(op_name); WriteComma(); new ExpressionListBlock(Emitter, new Expression[] { BinaryOperatorExpression.Left, BinaryOperatorExpression.Right }, null, null, 0) .Emit(); AddOveflowFlag(typeCode, op_name); WriteCloseParentheses(); } else { BinaryOperatorExpression.Left.AcceptVisitor(Emitter); WriteDot(); Write(op_name); WriteOpenParentheses(); BinaryOperatorExpression.Right.AcceptVisitor(Emitter); AddOveflowFlag(typeCode, op_name); WriteCloseParentheses(); } } }
protected void VisitForeachStatement(bool?replaceAwaiterByVar = null) { ForeachStatement foreachStatement = ForeachStatement; var jumpStatements = Emitter.JumpStatements; Emitter.JumpStatements = null; if (foreachStatement.EmbeddedStatement is EmptyStatement) { return; } WriteSourceMapName(foreachStatement.VariableName); var iteratorVar = GetTempVarName(); var iteratorName = AddLocal(iteratorVar, null, AstType.Null); var rr = (ForEachResolveResult)Emitter.Resolver.ResolveNode(foreachStatement); var get_rr = rr.GetEnumeratorCall as InvocationResolveResult; var in_rr = Emitter.Resolver.ResolveNode(foreachStatement.InExpression); var inline = get_rr != null?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; Write(iteratorName, " = "); if (!emitInline) { Write(JS.Funcs.H5_GET_ENUMERATOR); WriteOpenParentheses(); foreachStatement.InExpression.AcceptVisitor(Emitter); } if (checkEnum) { if (isGenericEnumerable) { WriteComma(false); Write(H5Types.ToJsName(((ParameterizedType)rr.CollectionType).TypeArguments[0], Emitter)); } else if (get_rr != null) { if (inline != null) { var argsInfo = new ArgumentsInfo(Emitter, foreachStatement.InExpression, get_rr); new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit(); } else { var name = OverloadsCollection.Create(Emitter, get_rr.Member).GetOverloadName(); if (name != "GetEnumerator" && name != "System$Collections$IEnumerable$GetEnumerator") { WriteComma(false); WriteScript(name); } } } } if (!emitInline) { WriteCloseParentheses(); } WriteSemiColon(); WriteNewLine(); WriteTry(); BeginBlock(); WriteWhile(); WriteOpenParentheses(); Write(iteratorName); WriteDot(); Write(JS.Funcs.MOVE_NEXT); WriteOpenCloseParentheses(); WriteCloseParentheses(); WriteSpace(); BeginBlock(); PushLocals(); Action ac = () => { bool isReferenceLocal = false; if (Emitter.LocalsMap != null && Emitter.LocalsMap.ContainsKey(rr.ElementVariable)) { isReferenceLocal = Emitter.LocalsMap[rr.ElementVariable].EndsWith(".v"); } var varName = AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType); WriteVar(); Write(varName + " = "); if (isReferenceLocal) { Write("{ v : "); } string castCode = GetCastCode(rr.ElementType, rr.ElementVariable.Type); if (castCode != null) { EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode); } else if (CastMethod != null) { Write(H5Types.ToJsName(CastMethod.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, CastMethod).GetOverloadName()); WriteOpenParentheses(); int pos = Emitter.Output.Length; Write(iteratorName + "." + JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos); WriteCloseParentheses(); } else { var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type); if (needCast) { Write(JS.Funcs.H5_CAST); WriteOpenParentheses(); } int pos = Emitter.Output.Length; Write(iteratorName); WriteDot(); Write(JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos); if (needCast) { Write(", ", H5Types.ToJsName(rr.ElementVariable.Type, Emitter), ")"); } } if (isReferenceLocal) { Write(" }"); } WriteSemiColon(); WriteNewLine(); }; Emitter.BeforeBlock = ac; if (replaceAwaiterByVar.HasValue) { Emitter.ReplaceAwaiterByVar = replaceAwaiterByVar.Value; } if (foreachStatement.EmbeddedStatement is BlockStatement block) { Emitter.NoBraceBlock = block; } foreachStatement.EmbeddedStatement.AcceptVisitor(Emitter); PopLocals(); if (!Emitter.IsNewLine) { WriteNewLine(); } EndBlock(); WriteNewLine(); EndBlock(); WriteSpace(); WriteFinally(); BeginBlock(); Write($"if ({JS.Types.H5.IS}({iteratorName}, {JS.Types.System.IDisposable.NAME})) "); BeginBlock(); Write($"{iteratorName}.{JS.Types.System.IDisposable.INTERFACE_DISPOSE}();"); WriteNewLine(); EndBlock(); WriteNewLine(); EndBlock(); WriteNewLine(); Emitter.JumpStatements = jumpStatements; }
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 BuildArgumentsList(IList <Expression> arguments) { Expression paramsArg = null; string paramArgName = null; var resolveResult = ResolveResult; if (resolveResult != null) { var parameters = resolveResult.Member.Parameters; var isDelegate = resolveResult.Member.DeclaringType.Kind == TypeKind.Delegate; int shift = 0; if (resolveResult.Member is IMethod resolvedMethod && resolveResult is CSharpInvocationResolveResult invocationResult && resolvedMethod.IsExtensionMethod && invocationResult.IsExtensionMethodInvocation) { shift = 1; ThisName = resolvedMethod.Parameters[0].Name; IsExtensionMethod = true; } Expression[] result = new Expression[parameters.Count - shift]; string[] names = new string[result.Length]; bool named = false; int i = 0; bool isInterfaceMember = false; if (resolveResult.Member != null) { var inlineStr = Emitter.GetInline(resolveResult.Member); named = !string.IsNullOrEmpty(inlineStr); isInterfaceMember = resolveResult.Member.DeclaringTypeDefinition != null && resolveResult.Member.DeclaringTypeDefinition.Kind == TypeKind.Interface; } var expandParams = resolveResult.Member.Attributes.Any(a => a.AttributeType.FullName == "H5.ExpandParamsAttribute"); foreach (var arg in arguments) { if (arg is NamedArgumentExpression namedArg) { var namedParam = parameters.First(p => p.Name == namedArg.Name); var index = parameters.IndexOf(namedParam) - shift; result[index] = namedArg.Expression; names[index] = namedArg.Name; named = true; if (paramsArg == null && parameters.FirstOrDefault(p => p.Name == namedArg.Name).IsParams) { if (resolveResult.Member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(resolveResult.Member.DeclaringTypeDefinition)) { paramsArg = namedArg.Expression; } paramArgName = namedArg.Name; } } else { if (paramsArg == null && (parameters.Count > (i + shift)) && parameters[i + shift].IsParams) { if (resolveResult.Member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(resolveResult.Member.DeclaringTypeDefinition) || expandParams) { paramsArg = arg; } paramArgName = parameters[i + shift].Name; } if (i >= result.Length) { var list = result.ToList(); list.AddRange(new Expression[arguments.Count - i]); var strList = names.ToList(); strList.AddRange(new string[arguments.Count - i]); result = list.ToArray(); names = strList.ToArray(); } result[i] = arg; names[i] = (i + shift) < parameters.Count ? parameters[i + shift].Name : paramArgName; } i++; } for (i = 0; i < result.Length; i++) { if (result[i] == null) { var p = parameters[i + shift]; object t = null; if (p.Type.Kind == TypeKind.Enum) { t = Helpers.GetEnumValue(Emitter, p.Type, p.ConstantValue); } else { t = p.ConstantValue; } if ((named || isInterfaceMember || isDelegate) && !p.IsParams) { if (t == null) { result[i] = new PrimitiveExpression(new RawValue("void 0")); } else { result[i] = new PrimitiveExpression(t); } } names[i] = parameters[i + shift].Name; } } ArgumentsExpressions = result; ArgumentsNames = names; ParamsExpression = paramsArg; NamedExpressions = CreateNamedExpressions(names, result); } else { ArgumentsExpressions = arguments.ToArray(); } }
private void BuildDynamicArgumentsList(DynamicInvocationResolveResult drr, IList <Expression> arguments) { Expression paramsArg = null; string paramArgName = null; IMethod method = null; if (drr.Target is MethodGroupResolveResult group && group.Methods.Count() > 1) { method = group.Methods.FirstOrDefault(m => { if (drr.Arguments.Count != m.Parameters.Count) { return(false); } for (int i = 0; i < m.Parameters.Count; i++) { var argType = drr.Arguments[i].Type; if (argType.Kind == TypeKind.Dynamic) { argType = Emitter.Resolver.Compilation.FindType(TypeCode.Object); } if (!m.Parameters[i].Type.Equals(argType)) { return(false); } } return(true); }); if (method == null) { throw new EmitterException(Expression, Constants.Messages.Exceptions.DYNAMIC_INVOCATION_TOO_MANY_OVERLOADS); } } if (method != null) { var member = method; var parameters = method.Parameters; Expression[] result = new Expression[parameters.Count]; string[] names = new string[result.Length]; bool named = false; int i = 0; bool isInterfaceMember = false; if (member != null) { var inlineStr = Emitter.GetInline(member); named = !string.IsNullOrEmpty(inlineStr); isInterfaceMember = member.DeclaringTypeDefinition != null && member.DeclaringTypeDefinition.Kind == TypeKind.Interface; } foreach (var arg in arguments) { if (arg is NamedArgumentExpression namedArg) { var namedParam = parameters.First(p => p.Name == namedArg.Name); var index = parameters.IndexOf(namedParam); result[index] = namedArg.Expression; names[index] = namedArg.Name; named = true; if (paramsArg == null && (parameters.Count > i) && parameters[i].IsParams) { if (member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(member.DeclaringTypeDefinition)) { paramsArg = namedArg.Expression; } paramArgName = namedArg.Name; } } else { if (paramsArg == null && (parameters.Count > i) && parameters[i].IsParams) { if (member.DeclaringTypeDefinition == null || !Emitter.Validator.IsExternalType(member.DeclaringTypeDefinition)) { paramsArg = arg; } paramArgName = parameters[i].Name; } if (i >= result.Length) { var list = result.ToList(); list.AddRange(new Expression[arguments.Count - i]); var strList = names.ToList(); strList.AddRange(new string[arguments.Count - i]); result = list.ToArray(); names = strList.ToArray(); } result[i] = arg; names[i] = i < parameters.Count ? parameters[i].Name : paramArgName; } i++; } for (i = 0; i < result.Length; i++) { if (result[i] == null) { var p = parameters[i]; object t = null; if (p.Type.Kind == TypeKind.Enum) { t = Helpers.GetEnumValue(Emitter, p.Type, p.ConstantValue); } else { t = p.ConstantValue; } if ((named || isInterfaceMember) && !p.IsParams) { if (t == null) { result[i] = new PrimitiveExpression(new RawValue("void 0")); } else { result[i] = new PrimitiveExpression(t); } } names[i] = parameters[i].Name; } } ArgumentsExpressions = result; ArgumentsNames = names; ParamsExpression = paramsArg; NamedExpressions = CreateNamedExpressions(names, result); } else { ArgumentsExpressions = arguments.ToArray(); } }
public IMethod GetCastMethod(IType fromType, IType toType, out string template) { string inline = null; var method = fromType.GetMethods().FirstOrDefault(m => { if (m.IsOperator && (m.Name == "op_Explicit" || m.Name == "op_Implicit") && m.Parameters.Count == 1 && m.ReturnType.ReflectionName == toType.ReflectionName && m.Parameters[0].Type.ReflectionName == fromType.ReflectionName ) { string tmpInline = Emitter.GetInline(m); if (!string.IsNullOrWhiteSpace(tmpInline)) { inline = tmpInline; return(true); } } return(false); }); if (method == null) { method = toType.GetMethods().FirstOrDefault(m => { if (m.IsOperator && (m.Name == "op_Explicit" || m.Name == "op_Implicit") && m.Parameters.Count == 1 && m.ReturnType.ReflectionName == toType.ReflectionName && (m.Parameters[0].Type.ReflectionName == fromType.ReflectionName) ) { string tmpInline = Emitter.GetInline(m); if (!string.IsNullOrWhiteSpace(tmpInline)) { inline = tmpInline; return(true); } } return(false); }); } if (method == null && CastExpression != null) { var conversion = Emitter.Resolver.Resolver.GetConversion(CastExpression); if (conversion.IsUserDefined) { method = conversion.Method; string tmpInline = Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(tmpInline)) { inline = tmpInline; } } } template = inline; return(method); }
protected virtual void EmitMethods(Dictionary <string, List <MethodDeclaration> > methods, Dictionary <string, List <EntityDeclaration> > properties, Dictionary <OperatorType, List <OperatorDeclaration> > operators) { int pos = Emitter.Output.Length; var writerInfo = SaveWriter(); string globalTarget = H5Types.GetGlobalTarget(TypeInfo.Type.GetDefinition(), TypeInfo.TypeDeclaration); if (globalTarget == null) { EnsureComma(); Write(JS.Fields.METHODS); WriteColon(); BeginBlock(); } int checkPos = Emitter.Output.Length; var names = new List <string>(properties.Keys); foreach (var name in names) { var props = properties[name]; foreach (var prop in props) { if (prop is PropertyDeclaration) { Emitter.VisitPropertyDeclaration((PropertyDeclaration)prop); } else if (prop is CustomEventDeclaration) { Emitter.VisitCustomEventDeclaration((CustomEventDeclaration)prop); } else if (prop is IndexerDeclaration) { Emitter.VisitIndexerDeclaration((IndexerDeclaration)prop); } } } names = new List <string>(methods.Keys); foreach (var name in names) { EmitMethodsGroup(methods[name]); } if (operators != null) { var ops = new List <OperatorType>(operators.Keys); foreach (var op in ops) { EmitOperatorGroup(operators[op]); } } if (TypeInfo.ClassType == ClassType.Struct) { if (!StaticBlock) { EmitStructMethods(); } else { string structName = H5Types.ToJsName(TypeInfo.Type, Emitter); if (TypeInfo.Type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(TypeInfo.Type, Emitter)) { structName = "(" + structName + ")"; } EnsureComma(); Write(JS.Funcs.GETDEFAULTVALUE + ": function () { return new " + structName + "(); }"); Emitter.Comma = true; } } else if (StaticBlock) { var ctor = TypeInfo.Type.GetConstructors().FirstOrDefault(c => c.Parameters.Count == 0 && Emitter.GetInline(c) != null); if (ctor != null) { var code = Emitter.GetInline(ctor); EnsureComma(); Write(JS.Funcs.GETDEFAULTVALUE + ": function () "); BeginBlock(); Write("return "); var argsInfo = new ArgumentsInfo(Emitter, ctor); new InlineArgumentsBlock(Emitter, argsInfo, code).Emit(); Write(";"); WriteNewLine(); EndBlock(); Emitter.Comma = true; } } if (globalTarget == null) { if (checkPos == Emitter.Output.Length) { Emitter.IsNewLine = writerInfo.IsNewLine; Emitter.ResetLevel(writerInfo.Level); Emitter.Comma = writerInfo.Comma; Emitter.Output.Length = pos; } else { WriteNewLine(); EndBlock(); } } }
protected void VisitObjectCreateExpression() { ObjectCreateExpression objectCreateExpression = ObjectCreateExpression; var resolveResult = Emitter.Resolver.ResolveNode(objectCreateExpression.Type) as TypeResolveResult; if (resolveResult != null && resolveResult.Type.Kind == TypeKind.Enum) { Write("(0)"); return; } bool isTypeParam = resolveResult != null && resolveResult.Type.Kind == TypeKind.TypeParameter; var invocationResolveResult = Emitter.Resolver.ResolveNode(objectCreateExpression) as InvocationResolveResult; var hasInitializer = !objectCreateExpression.Initializer.IsNull && objectCreateExpression.Initializer.Elements.Count > 0; if (isTypeParam && invocationResolveResult != null && invocationResolveResult.Member.Parameters.Count == 0 && !hasInitializer) { Write(JS.Funcs.H5_CREATEINSTANCE); WriteOpenParentheses(); Write(resolveResult.Type.Name); WriteCloseParentheses(); return; } var type = isTypeParam ? null : Emitter.GetTypeDefinition(objectCreateExpression.Type); var isObjectLiteral = type != null && Emitter.Validator.IsObjectLiteral(type); if (type != null && type.BaseType != null && type.BaseType.FullName == "System.MulticastDelegate") { bool wrap = false; if (objectCreateExpression.Parent is InvocationExpression parent && parent.Target == objectCreateExpression) { wrap = true; } if (wrap) { WriteOpenParentheses(); } Write("H5.fn.$build(["); objectCreateExpression.Arguments.First().AcceptVisitor(Emitter); Write("])"); if (wrap) { WriteCloseParentheses(); } return; } var argsInfo = new ArgumentsInfo(Emitter, objectCreateExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; string inlineCode = null; if (invocationResolveResult != null) { if (invocationResolveResult.Member.DeclaringType.Kind == TypeKind.Struct && objectCreateExpression.Arguments.Count == 0) { var ctors = invocationResolveResult.Member.DeclaringType.GetConstructors(c => c.Parameters.Count == 1); var defCtor = ctors.FirstOrDefault(c => c.Parameters.First().Type.FullName == "System.Runtime.CompilerServices.DummyTypeUsedToAddAttributeToDefaultValueTypeConstructor"); if (defCtor != null) { inlineCode = Emitter.GetInline(defCtor); } } if (inlineCode == null) { inlineCode = Emitter.GetInline(invocationResolveResult.Member); } } var customCtor = isTypeParam ? "" : (Emitter.Validator.GetCustomConstructor(type) ?? ""); AstNodeCollection <Expression> elements = null; if (hasInitializer) { elements = objectCreateExpression.Initializer.Elements; } var isPlainObjectCtor = Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success; var isPlainMode = type != null && Emitter.Validator.GetObjectCreateMode(type) == 0; if (inlineCode == null && isPlainObjectCtor && isPlainMode) { WriteOpenBrace(); WriteSpace(); var pos = Emitter.Output.Length; WriteObjectInitializer(objectCreateExpression.Initializer.Elements, type, invocationResolveResult, false); if (pos < Emitter.Output.Length) { WriteSpace(); } WriteCloseBrace(); } else { string tempVar = null; if (hasInitializer) { tempVar = GetTempVarName(); WriteOpenParentheses(); Write(tempVar); Write(" = "); } if (inlineCode != null) { new InlineArgumentsBlock(Emitter, argsInfo, inlineCode).Emit(); } else { var ctorMember = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(objectCreateExpression)).Member; var expandParams = ctorMember.Attributes.Any(a => a.AttributeType.FullName == "H5.ExpandParamsAttribute"); bool applyCtor = false; if (expandParams) { var ctor_rr = Emitter.Resolver.ResolveNode(paramsArg); if (ctor_rr.Type.Kind == TypeKind.Array && !(paramsArg is ArrayCreateExpression) && objectCreateExpression.Arguments.Last() == paramsArg) { Write(JS.Types.H5.Reflection.APPLYCONSTRUCTOR + "("); applyCtor = true; } } if (String.IsNullOrEmpty(customCtor) || (isObjectLiteral && isPlainObjectCtor)) { if (!applyCtor && !isObjectLiteral) { WriteNew(); } var typerr = Emitter.Resolver.ResolveNode(objectCreateExpression.Type).Type; var td = typerr.GetDefinition(); var isGeneric = typerr.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(typerr, Emitter) || td != null && Validator.IsVirtualTypeStatic(td); if (isGeneric && !applyCtor) { WriteOpenParentheses(); } objectCreateExpression.Type.AcceptVisitor(Emitter); if (isGeneric && !applyCtor) { WriteCloseParentheses(); } } else { Write(customCtor); } if (!isTypeParam && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType || isObjectLiteral ? 0 : 1)) { var member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(objectCreateExpression)).Member; if (!Emitter.Validator.IsExternalType(type) || member.Attributes.Any(a => a.AttributeType.FullName == "H5.NameAttribute")) { WriteDot(); var name = OverloadsCollection.Create(Emitter, member).GetOverloadName(); Write(name); } } if (applyCtor) { Write(", "); } else { WriteOpenParentheses(); } new ExpressionListBlock(Emitter, argsExpressions, paramsArg, objectCreateExpression, -1).Emit(); WriteCloseParentheses(); } if (hasInitializer) { if (isObjectLiteral && isPlainMode) { WriteObjectInitializer(objectCreateExpression.Initializer.Elements, type, invocationResolveResult, true); } else { foreach (Expression item in elements) { WriteInitializerExpression(item, tempVar); } } WriteComma(); Write(tempVar); WriteCloseParentheses(); RemoveTempVar(tempVar); } } //Helpers.CheckValueTypeClone(invocationResolveResult, this.ObjectCreateExpression, this, pos); }
protected void VisitAsyncForeachStatement() { ForeachStatement foreachStatement = ForeachStatement; if (foreachStatement.EmbeddedStatement is EmptyStatement) { return; } var oldValue = Emitter.ReplaceAwaiterByVar; var jumpStatements = Emitter.JumpStatements; Emitter.JumpStatements = new List <IJumpInfo>(); WriteAwaiters(foreachStatement.InExpression); bool containsAwaits = false; var awaiters = GetAwaiters(foreachStatement.EmbeddedStatement); if (awaiters != null && awaiters.Length > 0) { containsAwaits = true; } Emitter.ReplaceAwaiterByVar = true; if (!containsAwaits) { VisitForeachStatement(oldValue); return; } var iteratorName = AddLocal(GetTempVarName(), null, AstType.Null); var for_rr = (ForEachResolveResult)Emitter.Resolver.ResolveNode(foreachStatement); var get_rr = for_rr.GetEnumeratorCall as InvocationResolveResult; var in_rr = Emitter.Resolver.ResolveNode(foreachStatement.InExpression); var inline = get_rr != null?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; Write(iteratorName, " = "); if (!emitInline) { Write(JS.Funcs.H5_GET_ENUMERATOR); WriteOpenParentheses(); foreachStatement.InExpression.AcceptVisitor(Emitter); } if (checkEnum) { if (for_rr.CollectionType.IsParameterized && for_rr.CollectionType.FullName == "System.Collections.Generic.IEnumerable") { WriteComma(false); Write(H5Types.ToJsName(((ParameterizedType)for_rr.CollectionType).TypeArguments[0], Emitter)); } else if (get_rr != null) { if (inline != null) { var argsInfo = new ArgumentsInfo(Emitter, foreachStatement.InExpression, get_rr); new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit(); } else { var name = OverloadsCollection.Create(Emitter, get_rr.Member).GetOverloadName(); if (name != "GetEnumerator" && name != "System$Collections$IEnumerable$GetEnumerator") { WriteComma(false); WriteScript(name); } } } } Emitter.ReplaceAwaiterByVar = oldValue; if (!emitInline) { WriteCloseParentheses(); } WriteSemiColon(); WriteNewLine(); Write(JS.Vars.ASYNC_STEP + " = " + Emitter.AsyncBlock.Step + ";"); WriteNewLine(); Write("continue;"); WriteNewLine(); IAsyncStep conditionStep = Emitter.AsyncBlock.AddAsyncStep(); WriteIf(); WriteOpenParentheses(); Write(iteratorName); WriteDot(); Write(JS.Funcs.MOVE_NEXT); WriteOpenCloseParentheses(); WriteCloseParentheses(); WriteSpace(); BeginBlock(); PushLocals(); var varName = AddLocal(foreachStatement.VariableName, foreachStatement.VariableNameToken, foreachStatement.VariableType); WriteVar(); Write(varName + " = "); var rr = Emitter.Resolver.ResolveNode(foreachStatement) as ForEachResolveResult; bool isReferenceLocal = false; if (Emitter.LocalsMap != null && Emitter.LocalsMap.ContainsKey(rr.ElementVariable)) { isReferenceLocal = Emitter.LocalsMap[rr.ElementVariable].EndsWith(".v"); } if (isReferenceLocal) { Write("{ v : "); } string castCode = GetCastCode(rr.ElementType, rr.ElementVariable.Type); if (castCode != null) { EmitInlineCast(iteratorName + "." + JS.Funcs.GET_CURRENT, castCode); } else if (CastMethod != null) { Write(H5Types.ToJsName(CastMethod.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, CastMethod).GetOverloadName()); WriteOpenParentheses(); var pos = Emitter.Output.Length; Write(iteratorName + "." + JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos); WriteCloseParentheses(); } else { var needCast = !rr.ElementType.Equals(rr.ElementVariable.Type); if (needCast) { Write(JS.Funcs.H5_CAST); WriteOpenParentheses(); } var pos = Emitter.Output.Length; Write(iteratorName); WriteDot(); Write(JS.Funcs.GET_CURRENT); Helpers.CheckValueTypeClone(rr, ForeachStatement.InExpression, this, pos); if (needCast) { Write(", ", H5Types.ToJsName(rr.ElementVariable.Type, Emitter), ")"); } } if (isReferenceLocal) { Write(" }"); } WriteSemiColon(); WriteNewLine(); Write(JS.Vars.ASYNC_STEP + " = " + Emitter.AsyncBlock.Step + ";"); WriteNewLine(); Write("continue;"); var writer = SaveWriter(); Emitter.AsyncBlock.AddAsyncStep(); Emitter.IgnoreBlock = foreachStatement.EmbeddedStatement; var startCount = Emitter.AsyncBlock.Steps.Count; if (foreachStatement.EmbeddedStatement is BlockStatement block) { block.AcceptChildren(Emitter); } else { foreachStatement.EmbeddedStatement.AcceptVisitor(Emitter); } IAsyncStep loopStep = null; if (Emitter.AsyncBlock.Steps.Count > startCount) { loopStep = Emitter.AsyncBlock.Steps.Last(); loopStep.JumpToStep = conditionStep.Step; } RestoreWriter(writer); if (!IsJumpStatementLast(Emitter.Output.ToString())) { Write(JS.Vars.ASYNC_STEP + " = " + conditionStep.Step + ";"); WriteNewLine(); Write("continue;"); WriteNewLine(); } PopLocals(); WriteNewLine(); EndBlock(); WriteNewLine(); var nextStep = Emitter.AsyncBlock.AddAsyncStep(); conditionStep.JumpToStep = nextStep.Step; if (Emitter.JumpStatements.Count > 0) { Emitter.JumpStatements.Sort((j1, j2) => - j1.Position.CompareTo(j2.Position)); foreach (var jump in Emitter.JumpStatements) { jump.Output.Insert(jump.Position, jump.Break ? nextStep.Step : conditionStep.Step); } } Emitter.JumpStatements = jumpStatements; }
protected virtual void EmitIndexerMethod(IndexerDeclaration indexerDeclaration, IProperty prop, Accessor accessor, IMethod propAccessor, bool setter) { var isIgnore = propAccessor != null && Emitter.Validator.IsExternalType(propAccessor); if (!accessor.IsNull && Emitter.GetInline(accessor) == null && !isIgnore) { EnsureComma(); ResetLocals(); var prevMap = BuildLocalsMap(); var prevNamesMap = BuildLocalsNamesMap(); if (setter) { AddLocals(new ParameterDeclaration[] { new ParameterDeclaration { Name = "value" } }, accessor.Body); } else { AddLocals(new ParameterDeclaration[0], accessor.Body); } XmlToJsDoc.EmitComment(this, IndexerDeclaration, !setter); string accName = null; if (prop != null) { accName = Emitter.GetEntityNameFromAttr(prop, setter); if (string.IsNullOrEmpty(accName)) { var member_rr = (MemberResolveResult)Emitter.Resolver.ResolveNode(indexerDeclaration); var overloads = OverloadsCollection.Create(Emitter, indexerDeclaration, setter); accName = overloads.GetOverloadName(false, Helpers.GetSetOrGet(setter), OverloadsCollection.ExcludeTypeParameterForDefinition(member_rr)); } } Write(accName); WriteColon(); WriteFunction(); EmitMethodParameters(indexerDeclaration.Parameters, null, indexerDeclaration, setter); if (setter) { Write(", value)"); } WriteSpace(); var script = Emitter.GetScript(accessor); if (script == null) { if (YieldBlock.HasYield(accessor.Body)) { new GeneratorBlock(Emitter, accessor).Emit(); } else { accessor.Body.AcceptVisitor(Emitter); } } else { BeginBlock(); WriteLines(script); EndBlock(); } ClearLocalsMap(prevMap); ClearLocalsNamesMap(prevNamesMap); Emitter.Comma = true; } }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = IdentifierExpression; int pos = Emitter.Output.Length; ResolveResult resolveResult = null; isRefArg = Emitter.IsRefArg; Emitter.IsRefArg = false; resolveResult = Emitter.Resolver.ResolveNode(identifierExpression); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (Emitter.Locals != null && Emitter.Locals.ContainsKey(id) && resolveResult is LocalResolveResult) { var lrr = (LocalResolveResult)resolveResult; if (Emitter.LocalsMap != null && Emitter.LocalsMap.ContainsKey(lrr.Variable) && !(identifierExpression.Parent is DirectionExpression)) { Write(Emitter.LocalsMap[lrr.Variable]); } else if (Emitter.LocalsNamesMap != null && Emitter.LocalsNamesMap.ContainsKey(id)) { Write(Emitter.LocalsNamesMap[id]); } else { Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); return; } if (resolveResult is TypeResolveResult) { Write(H5Types.ToJsName(resolveResult.Type, Emitter)); /*if (this.Emitter.Validator.IsExternalType(resolveResult.Type.GetDefinition()) || resolveResult.Type.Kind == TypeKind.Enum) * { * this.Write(H5Types.ToJsName(resolveResult.Type, this.Emitter)); * } * else * { * this.Write("H5.get(" + H5Types.ToJsName(resolveResult.Type, this.Emitter) + ")"); * }*/ return; } string inlineCode = memberResult != null?Emitter.GetInline(memberResult.Member) : null; var isInvoke = identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression); if (memberResult != null && memberResult.Member is IMethod && isInvoke) { if (Emitter.Resolver.ResolveNode(identifierExpression.Parent) is CSharpInvocationResolveResult i_rr && !i_rr.IsExpandedForm) { var tpl = Emitter.GetAttribute(memberResult.Member.Attributes, JS.NS.H5 + ".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 == "(" ) ) { if (!(identifierExpression.Parent is InvocationExpression parentInvocation) || parentInvocation.Target != identifierExpression) { var method = (IMethod)memberResult.Member; if (method.TypeArguments.Count > 0) { inlineCode = MemberReferenceBlock.GenerateInlineForMethodReference(method, Emitter); } } } bool hasInline = !string.IsNullOrEmpty(inlineCode); inlineCode = hasInline ? Helpers.ConvertTokens(Emitter, inlineCode, memberResult.Member) : inlineCode; bool hasThis = hasInline && Helpers.HasThis(inlineCode); if (hasInline && inlineCode.StartsWith("<self>")) { hasThis = true; inlineCode = inlineCode.Substring(6); } if (hasThis) { Emitter.ThisRefCounter++; Write(""); var oldBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { Write(H5Types.ToJsName(memberResult.Member.DeclaringType, Emitter, ignoreLiteralName: false)); /*if (!this.Emitter.Validator.IsExternalType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum) * { * this.Write("(H5.get(" + H5Types.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); * } * else * { * this.Write(H5Types.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { WriteThis(); } var oldInline = inlineCode; var thisArg = Emitter.Output.ToString(); int thisIndex = inlineCode.IndexOf("{this}"); inlineCode = inlineCode.Replace("{this}", thisArg); Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { 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(Emitter, new ArgumentsInfo(Emitter, IdentifierExpression, resolveResult), oldInline, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else if (memberResult != null && memberResult.Member is IField && inlineCode.Contains("{0}")) { PushWriter(inlineCode, null, thisArg, range); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode)) { PushWriter(inlineCode, null, thisArg, range); } else { Write(inlineCode); } } return; } if (hasInline) { if (!memberResult.Member.IsStatic) { inlineCode = "this." + inlineCode; } if (resolveResult is InvocationResolveResult) { PushWriter(inlineCode); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, IdentifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode)) { PushWriter(inlineCode); } else { 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 (!(identifierExpression.Parent is InvocationExpression parentInvocation) || parentInvocation.Target != identifierExpression) { if (!string.IsNullOrEmpty(inlineCode)) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(Emitter, new ArgumentsInfo(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; Write(isExtensionMethod ? JS.Funcs.H5_BIND_SCOPE : JS.Funcs.H5_CACHE_BIND); WriteOpenParentheses(); WriteThis(); Write(", "); appendAdditionalCode = ")"; } } } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Field && Emitter.IsMemberConst(memberResult.Member) && Emitter.IsInlineConst(memberResult.Member)) { 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 (Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { WriteOpenParentheses(); valueVar = GetTempVarName(); Write(valueVar); Write(" = "); } } WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { //this.Write(inlineCode); if (resolveResult is InvocationResolveResult || (memberResult.Member.SymbolKind == SymbolKind.Property && Emitter.IsAssignment)) { PushWriter(inlineCode); } else { Write(inlineCode); } } else if (memberResult.Member is IProperty) { var name = Helpers.GetPropertyRef(memberResult.Member, Emitter); WriteIdentifier(name); } else if (!Emitter.IsAssignment) { if (Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, Emitter.Resolver); bool isLong = Helpers.Is64Type(memberResult.Member.ReturnType, Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, true)); WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); WriteOpenParentheses(); if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { WriteScript(JS.Funcs.Math.INC); } else { WriteScript(JS.Funcs.Math.DEC); } WriteComma(); WriteTarget(memberResult); Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false)); WriteOpenParentheses(); WriteCloseParentheses(); WriteCloseParentheses(); } else { WriteTarget(memberResult); Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false)); WriteOpenParentheses(); WriteCloseParentheses(); WriteDot(); if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { Write(JS.Funcs.Math.INC); } else { Write(JS.Funcs.Math.DEC); } WriteOpenParentheses(); WriteCloseParentheses(); } } else { WriteTarget(memberResult); Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false)); WriteOpenParentheses(); WriteCloseParentheses(); if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { Write("+"); } else { Write("-"); } Write("1"); } WriteCloseParentheses(); } else { Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false)); WriteOpenParentheses(); WriteCloseParentheses(); WriteComma(); WriteTarget(memberResult); Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, true)); WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); WriteOpenParentheses(); if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { WriteScript(JS.Funcs.Math.INC); } else { WriteScript(JS.Funcs.Math.DEC); } WriteComma(); Write(valueVar); WriteCloseParentheses(); } else { Write(valueVar); WriteDot(); if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { Write(JS.Funcs.Math.INC); } else { Write(JS.Funcs.Math.DEC); } WriteOpenParentheses(); WriteCloseParentheses(); } } else { Write(valueVar); if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { Write("+"); } else { Write("-"); } Write("1"); } WriteCloseParentheses(); WriteComma(); if (Emitter.UnaryOperatorType == UnaryOperatorType.Increment || Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { WriteTarget(memberResult); Write(Helpers.GetPropertyRef(memberResult.Member, Emitter, false)); WriteOpenParentheses(); WriteCloseParentheses(); } else { Write(valueVar); } WriteCloseParentheses(); if (valueVar != null) { RemoveTempVar(valueVar); } } } else { Write(Helpers.GetPropertyRef(memberResult.Member, Emitter)); WriteOpenParentheses(); WriteCloseParentheses(); } } else if (Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = H5Types.ToJsName(memberResult.Member.DeclaringType, Emitter, ignoreLiteralName: false); } 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; bool special = Emitter.Resolver.ResolveNode(identifierExpression.Parent) is OperatorResolveResult orr && orr.IsLiftedOperator; if (!special && isBool && (Emitter.AssignmentType == AssignmentOperatorType.BitwiseAnd || Emitter.AssignmentType == AssignmentOperatorType.BitwiseOr)) { skipGet = true; } if (skipGet) { PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, Emitter, true), "({0})")); } else { PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, Emitter, false), "()", "{0})")); } } else { PushWriter(Helpers.GetPropertyRef(memberResult.Member, Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is IEvent) { if (Emitter.IsAssignment && (Emitter.AssignmentType == AssignmentOperatorType.Add || Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { Write(inlineCode); } else { Write(Helpers.GetAddOrRemove(Emitter.AssignmentType == AssignmentOperatorType.Add)); Write( OverloadsCollection.Create(Emitter, memberResult.Member, Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } WriteOpenParentheses(); } else { WriteTarget(memberResult); Write(Emitter.GetEntityName(memberResult.Member)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { Write(inlineCode); } else if (isResolved) { if (resolveResult is LocalResolveResult localResolveResult) { Write(localResolveResult.Variable.Name); } else if (memberResult != null) { WriteTarget(memberResult); string name = OverloadsCollection.Create(Emitter, memberResult.Member).GetOverloadName(); if (isRefArg) { WriteScript(name); } else if (memberResult.Member is IField) { WriteIdentifier(name); } else { Write(name); } } else { Write(resolveResult.ToString()); } } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { Write(appendAdditionalCode); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); }
private void EmitExternalBaseCtor(ConstructorDeclaration ctor, ref bool requireNewLine) { IMember member = null; var hasInitializer = ctor.Initializer != null && !ctor.Initializer.IsNull; var baseType = Emitter.GetBaseTypeDefinition(); if (hasInitializer) { member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(ctor.Initializer)).Member; } if (member != null) { var inlineCode = Emitter.GetInline(member); if (!string.IsNullOrEmpty(inlineCode)) { if (requireNewLine) { WriteNewLine(); requireNewLine = false; } Write(JS.Types.H5.APPLY); WriteOpenParentheses(); Write("this, "); var argsInfo = new ArgumentsInfo(Emitter, ctor.Initializer); new InlineArgumentsBlock(Emitter, argsInfo, inlineCode).Emit(); WriteCloseParentheses(); WriteSemiColon(); WriteNewLine(); return; } } if (hasInitializer || (baseType.FullName != "System.Object" && baseType.FullName != "System.ValueType" && baseType.FullName != "System.Enum" && !baseType.CustomAttributes.Any(a => a.AttributeType.FullName == "H5.NonScriptableAttribute") && !baseType.IsInterface)) { if (requireNewLine) { WriteNewLine(); requireNewLine = false; } string name = null; if (TypeInfo.GetBaseTypes(Emitter).Any()) { name = H5Types.ToJsName(TypeInfo.GetBaseClass(Emitter), Emitter); } else { name = H5Types.ToJsName(baseType, Emitter); } Write(name); WriteCall(); int openPos = Emitter.Output.Length; WriteOpenParentheses(); Write("this"); if (hasInitializer && ctor.Initializer.Arguments.Count > 0) { Write(", "); var argsInfo = new ArgumentsInfo(Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } WriteCloseParentheses(); WriteSemiColon(); WriteNewLine(); } }
protected void VisitInvocationExpression() { InvocationExpression invocationExpression = InvocationExpression; int pos = Emitter.Output.Length; if (Emitter.IsForbiddenInvocation(invocationExpression)) { throw new EmitterException(invocationExpression, "This method cannot be invoked directly"); } var oldValue = Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = Emitter.AsyncExpressionHandling; if (Emitter.IsAsync && !Emitter.AsyncExpressionHandling) { WriteAwaiters(invocationExpression); Emitter.ReplaceAwaiterByVar = true; Emitter.AsyncExpressionHandling = true; } Tuple <bool, bool, string> inlineInfo = Emitter.GetInlineCode(invocationExpression); var argsInfo = new ArgumentsInfo(Emitter, invocationExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; var targetResolve = Emitter.Resolver.ResolveNode(invocationExpression); var csharpInvocation = targetResolve as CSharpInvocationResolveResult; MemberReferenceExpression targetMember = invocationExpression.Target as MemberReferenceExpression; bool isObjectLiteral = csharpInvocation != null && csharpInvocation.Member.DeclaringTypeDefinition != null?Emitter.Validator.IsObjectLiteral(csharpInvocation.Member.DeclaringTypeDefinition) : false; if (inlineInfo != null) { bool isStaticMethod = inlineInfo.Item1; bool isInlineMethod = inlineInfo.Item2; string inlineScript = inlineInfo.Item3; if (isInlineMethod) { if (invocationExpression.Arguments.Count > 0) { var code = invocationExpression.Arguments.First(); if (!(code is PrimitiveExpression inlineExpression)) { throw new EmitterException(invocationExpression, "Only primitive expression can be inlined"); } string value = inlineExpression.Value.ToString().Trim(); if (value.Length > 0) { value = InlineArgumentsBlock.ReplaceInlineArgs(this, inlineExpression.Value.ToString(), invocationExpression.Arguments.Skip(1).ToArray()); Write(value); value = value.Trim(); if (value[value.Length - 1] == ';' || value.EndsWith("*/", StringComparison.InvariantCulture) || value.StartsWith("//")) { Emitter.SkipSemiColon = true; WriteNewLine(); } } else { // Empty string, emit nothing. Emitter.SkipSemiColon = true; } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { bool isBase = invocationExpression.Target is MemberReferenceExpression targetMemberRef && targetMemberRef.Target is BaseReferenceExpression; if (!String.IsNullOrEmpty(inlineScript) && (isBase || invocationExpression.Target is IdentifierExpression)) { argsInfo.ThisArgument = "this"; bool noThis = !Helpers.HasThis(inlineScript); if (inlineScript.StartsWith("<self>")) { noThis = false; inlineScript = inlineScript.Substring(6); } if (!noThis) { Emitter.ThisRefCounter++; } if (!isStaticMethod && noThis) { WriteThis(); WriteDot(); } new InlineArgumentsBlock(Emitter, argsInfo, inlineScript).Emit(); Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } if (targetMember != null || isObjectLiteral) { var member = targetMember != null?Emitter.Resolver.ResolveNode(targetMember.Target) : null; if (targetResolve != null) { InvocationResolveResult invocationResult; bool isExtensionMethodInvocation = false; if (csharpInvocation != null) { if (member != null && member.Type.Kind == TypeKind.Delegate && (/*csharpInvocation.Member.Name == "Invoke" || */ csharpInvocation.Member.Name == "BeginInvoke" || csharpInvocation.Member.Name == "EndInvoke") && !csharpInvocation.IsExtensionMethodInvocation) { throw new EmitterException(invocationExpression, "Delegate's 'Invoke' methods are not supported. Please use direct delegate invoke."); } if (csharpInvocation.IsExtensionMethodInvocation) { invocationResult = csharpInvocation; isExtensionMethodInvocation = true; if (invocationResult.Member is IMethod resolvedMethod && resolvedMethod.IsExtensionMethod) { string inline = Emitter.GetInline(resolvedMethod); bool isNative = IsNativeMethod(resolvedMethod); if (string.IsNullOrWhiteSpace(inline) && isNative) { invocationResult = null; } } } else { invocationResult = null; } if (IsEmptyPartialInvoking(csharpInvocation.Member as IMethod) || IsConditionallyRemoved(invocationExpression, csharpInvocation.Member)) { Emitter.SkipSemiColon = true; Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null && (IsEmptyPartialInvoking(invocationResult.Member as IMethod) || IsConditionallyRemoved(invocationExpression, invocationResult.Member))) { Emitter.SkipSemiColon = true; Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } if (invocationResult == null) { invocationResult = Emitter.Resolver.ResolveNode(invocationExpression) as InvocationResolveResult; } if (invocationResult != null) { if (invocationResult.Member is IMethod resolvedMethod && (resolvedMethod.IsExtensionMethod || isObjectLiteral)) { string inline = Emitter.GetInline(resolvedMethod); bool isNative = IsNativeMethod(resolvedMethod); if (isExtensionMethodInvocation || isObjectLiteral) { if (!string.IsNullOrWhiteSpace(inline)) { Write(""); StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = Emitter.Output.ToString(); Emitter.Output = savedBuilder; new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit(); } else if (!isNative) { var overloads = OverloadsCollection.Create(Emitter, resolvedMethod); if (isObjectLiteral && !resolvedMethod.IsStatic && resolvedMethod.DeclaringType.Kind == TypeKind.Interface) { Write("H5.getType("); WriteThisExtension(invocationExpression.Target); Write(")."); } else { string name = H5Types.ToJsName(resolvedMethod.DeclaringType, Emitter, ignoreLiteralName: false) + "."; Write(name); } if (isObjectLiteral && !resolvedMethod.IsStatic) { Write(JS.Fields.PROTOTYPE + "." + overloads.GetOverloadName() + "." + JS.Funcs.CALL); } else { Write(overloads.GetOverloadName()); } var isIgnoreClass = resolvedMethod.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(resolvedMethod.DeclaringTypeDefinition); int openPos = Emitter.Output.Length; WriteOpenParentheses(); Emitter.Comma = false; if (isObjectLiteral && !resolvedMethod.IsStatic) { WriteThisExtension(invocationExpression.Target); Emitter.Comma = true; } if (!isIgnoreClass && !Helpers.IsIgnoreGeneric(resolvedMethod, Emitter) && argsInfo.HasTypeArguments) { EnsureComma(false); new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); Emitter.Comma = true; } if (!isObjectLiteral && resolvedMethod.IsStatic) { EnsureComma(false); WriteThisExtension(invocationExpression.Target); Emitter.Comma = true; } if (invocationExpression.Arguments.Count > 0) { EnsureComma(false); } new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); WriteCloseParentheses(); } if (!string.IsNullOrWhiteSpace(inline) || !isNative) { Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else if (isNative) { if (!string.IsNullOrWhiteSpace(inline)) { Write(""); StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = Emitter.Output.ToString(); Emitter.Output = savedBuilder; new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit(); } else { argsExpressions.First().AcceptVisitor(Emitter); WriteDot(); string name = Emitter.GetEntityName(resolvedMethod); Write(name); int openPos = Emitter.Output.Length; WriteOpenParentheses(); new ExpressionListBlock(Emitter, argsExpressions.Skip(1), paramsArg, invocationExpression, openPos).Emit(); WriteCloseParentheses(); } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } } } var proto = false; if (targetMember != null && targetMember.Target is BaseReferenceExpression) { if (Emitter.Resolver.ResolveNode(targetMember) is MemberResolveResult rr) { proto = rr.IsVirtualCall; /*var method = rr.Member as IMethod; * if (method != null && method.IsVirtual) * { * proto = true; * } * else * { * var prop = rr.Member as IProperty; * * if (prop != null && prop.IsVirtual) * { * proto = true; * } * }*/ } } if (proto) { var baseType = Emitter.GetBaseMethodOwnerTypeDefinition(targetMember.MemberName, targetMember.TypeArguments.Count); bool isIgnore = Emitter.Validator.IsExternalType(baseType); bool needComma = false; var resolveResult = Emitter.Resolver.ResolveNode(targetMember); string name = null; if (Emitter.TypeInfo.GetBaseTypes(Emitter).Any()) { name = H5Types.ToJsName(Emitter.TypeInfo.GetBaseClass(Emitter), Emitter); } else { name = H5Types.ToJsName(baseType, Emitter); } string baseMethod; bool isIgnoreGeneric = false; if (resolveResult is MemberResolveResult memberResult) { baseMethod = OverloadsCollection.Create(Emitter, memberResult.Member).GetOverloadName(); isIgnoreGeneric = Helpers.IsIgnoreGeneric(memberResult.Member, Emitter); } else { baseMethod = targetMember.MemberName; baseMethod = Object.Net.Utilities.StringUtils.ToLowerCamelCase(baseMethod); } Write(name, "." + JS.Fields.PROTOTYPE + ".", baseMethod); WriteCall(); WriteOpenParentheses(); WriteThis(); Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); } needComma = false; foreach (var arg in argsExpressions) { if (arg == null) { continue; } EnsureComma(false); if (needComma) { WriteComma(); } needComma = true; arg.AcceptVisitor(Emitter); } Emitter.Comma = false; WriteCloseParentheses(); } else { IMethod method = null; if (Emitter.Resolver.ResolveNode(invocationExpression) is DynamicInvocationResolveResult dynamicResolveResult) { if (dynamicResolveResult.Target is MethodGroupResolveResult group && group.Methods.Count() > 1) { 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 = Emitter.Resolver.Compilation.FindType(TypeCode.Object); } if (!m.Parameters[i].Type.Equals(argType)) { return(false); } } return(true); }); if (method == null) { throw new EmitterException(invocationExpression, Constants.Messages.Exceptions.DYNAMIC_INVOCATION_TOO_MANY_OVERLOADS); } } } else { var targetResolveResult = Emitter.Resolver.ResolveNode(invocationExpression.Target); if (targetResolveResult is MemberResolveResult invocationResolveResult) { method = invocationResolveResult.Member as IMethod; } } if (IsEmptyPartialInvoking(method) || IsConditionallyRemoved(invocationExpression, method)) { Emitter.SkipSemiColon = true; Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } bool isIgnore = method != null && method.DeclaringTypeDefinition != null && Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition); bool needExpand = false; if (method != null) { string paramsName = null; var paramsParam = method.Parameters.FirstOrDefault(p => p.IsParams); if (paramsParam != null) { paramsName = paramsParam.Name; } if (paramsName != null) { if (csharpInvocation != null && !csharpInvocation.IsExpandedForm) { needExpand = true; } } } int count = Emitter.Writers.Count; invocationExpression.Target.AcceptVisitor(Emitter); if (Emitter.Writers.Count > count) { var writer = Emitter.Writers.Pop(); if (method != null && method.IsExtensionMethod) { StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = Emitter.Output.ToString(); Emitter.Output = savedBuilder; } else if (writer.ThisArg != null) { argsInfo.ThisArgument = writer.ThisArg; } new InlineArgumentsBlock(Emitter, argsInfo, writer.InlineCode) { IgnoreRange = writer.IgnoreRange }.Emit(); var result = Emitter.Output.ToString(); Emitter.Output = writer.Output; Emitter.IsNewLine = writer.IsNewLine; Write(result); if (writer.Callback != null) { writer.Callback.Invoke(); } } else { if (needExpand && isIgnore) { Write("." + JS.Funcs.APPLY); } int openPos = Emitter.Output.Length; WriteOpenParentheses(); bool isIgnoreGeneric = false; if (targetResolve is InvocationResolveResult invocationResult) { isIgnoreGeneric = Helpers.IsIgnoreGeneric(invocationResult.Member, Emitter); } bool isWrapRest = false; if (needExpand && isIgnore) { StringBuilder savedBuilder = Emitter.Output; Emitter.Output = new StringBuilder(); WriteThisExtension(invocationExpression.Target); var thisArg = Emitter.Output.ToString(); Emitter.Output = savedBuilder; Write(thisArg); Emitter.Comma = true; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); } EnsureComma(false); if (argsExpressions.Length > 1) { WriteOpenBracket(); var elb = new ExpressionListBlock(Emitter, argsExpressions.Take(argsExpressions.Length - 1).ToArray(), paramsArg, invocationExpression, openPos); elb.IgnoreExpandParams = true; elb.Emit(); WriteCloseBracket(); Write(".concat("); elb = new ExpressionListBlock(Emitter, new Expression[] { argsExpressions[argsExpressions.Length - 1] }, paramsArg, invocationExpression, openPos); elb.IgnoreExpandParams = true; elb.Emit(); Write(")"); } else { new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, -1).Emit(); } } else { if (method != null && method.Attributes.Any(a => a.AttributeType.FullName == "H5.WrapRestAttribute")) { isWrapRest = true; } Emitter.Comma = false; if (!isIgnore && !isIgnoreGeneric && argsInfo.HasTypeArguments) { new TypeExpressionListBlock(Emitter, argsInfo.TypeArguments).Emit(); } if (invocationExpression.Arguments.Count > 0 || argsExpressions.Length > 0 && !argsExpressions.All(expr => expr == null)) { EnsureComma(false); } new ExpressionListBlock(Emitter, argsExpressions, paramsArg, invocationExpression, openPos).Emit(); } if (isWrapRest) { EnsureComma(false); Write("H5.fn.bind(this, function () "); BeginBlock(); Emitter.WrapRestCounter++; Emitter.SkipSemiColon = true; } else { Emitter.Comma = false; WriteCloseParentheses(); } } } if (targetResolve is InvocationResolveResult irr && irr.Member.MemberDefinition != null && irr.Member.MemberDefinition.ReturnType.Kind == TypeKind.TypeParameter) { Helpers.CheckValueTypeClone(Emitter.Resolver.ResolveNode(invocationExpression), invocationExpression, this, pos); } Emitter.ReplaceAwaiterByVar = oldValue; Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; }
private void WritePart(Expression expression, bool toString, ResolveResult rr, bool isCoalescing = false) { if (isCoalescing) { expressionInWork.Add(expression); } bool wrapString = false; if (NullStringCheck && rr.Type.IsKnownType(KnownTypeCode.String)) { wrapString = !(expression is BinaryOperatorExpression) && !(expression is PrimitiveExpression || rr.Type.IsReferenceType != null && !rr.Type.IsReferenceType.Value); } if (toString) { var toStringMethod = rr.Type.GetMembers().FirstOrDefault(m => { if (m.Name == CS.Methods.TOSTRING && !m.IsStatic && m.ReturnType.IsKnownType(KnownTypeCode.String) && m.IsOverride) { if (m is IMethod method && method.Parameters.Count == 0 && method.TypeParameters.Count == 0) { return(true); } } return(false); }); if (toStringMethod != null) { var inline = Emitter.GetInline(toStringMethod); if (inline != null) { var writer = new Writer { InlineCode = inline, Output = Emitter.Output, IsNewLine = Emitter.IsNewLine }; Emitter.IsNewLine = false; Emitter.Output = new StringBuilder(); expression.AcceptVisitor(Emitter); string result = Emitter.Output.ToString(); Emitter.Output = writer.Output; Emitter.IsNewLine = writer.IsNewLine; var argsInfo = new ArgumentsInfo(Emitter, expression, (IMethod)toStringMethod); argsInfo.ArgumentsExpressions = new Expression[] { expression }; argsInfo.ArgumentsNames = new string[] { "this" }; argsInfo.ThisArgument = result; new InlineArgumentsBlock(Emitter, argsInfo, writer.InlineCode).Emit(); return; } } } if (wrapString) { Write("("); } expression.AcceptVisitor(Emitter); if (wrapString) { Write(" || \"\")"); } if (isCoalescing) { expressionInWork.Remove(expression); } }
public virtual void EmitPropertyMethod(PropertyDeclaration propertyDeclaration, Accessor accessor, IMethod method, bool setter, bool isObjectLiteral) { if ((!accessor.IsNull || method != null && Helpers.IsScript(method)) && Emitter.GetInline(accessor) == null) { EnsureComma(); ResetLocals(); var prevMap = BuildLocalsMap(); var prevNamesMap = BuildLocalsNamesMap(); if (setter) { AddLocals(new ParameterDeclaration[] { new ParameterDeclaration { Name = "value" } }, accessor.Body); } else { AddLocals(new ParameterDeclaration[0], accessor.Body); } //XmlToJsDoc.EmitComment(this, this.PropertyDeclaration); Write(setter ? JS.Funcs.Property.SET : JS.Funcs.Property.GET); WriteColon(); WriteFunction(); var m_rr = (MemberResolveResult)Emitter.Resolver.ResolveNode(propertyDeclaration); WriteOpenParentheses(); Write(setter ? "value" : ""); WriteCloseParentheses(); WriteSpace(); var script = Emitter.GetScript(accessor); if (script == null) { if (YieldBlock.HasYield(accessor.Body)) { new GeneratorBlock(Emitter, accessor).Emit(); } else { accessor.Body.AcceptVisitor(Emitter); } } else { BeginBlock(); WriteLines(script); EndBlock(); } ClearLocalsMap(prevMap); ClearLocalsNamesMap(prevNamesMap); Emitter.Comma = true; } }
protected override void DoEmit() { IAttribute attribute = Attribute; var type = Emitter.GetTypeDefinition(attribute.AttributeType); var argsInfo = new ArgumentsInfo(Emitter, attribute); string inlineCode = Emitter.GetInline(attribute.Constructor); var customCtor = Emitter.Validator.GetCustomConstructor(type) ?? ""; var hasInitializer = attribute.NamedArguments.Count > 0; if (inlineCode == null && Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success) { WriteOpenBrace(); WriteSpace(); if (hasInitializer) { WriteObjectInitializer(attribute.NamedArguments, type, attribute); WriteSpace(); } else if (Emitter.Validator.IsObjectLiteral(type)) { WriteObjectInitializer(null, type, attribute); WriteSpace(); } WriteCloseBrace(); } else { if (hasInitializer) { Write(JS.Types.H5.APPLY); WriteOpenParentheses(); } if (inlineCode != null) { new InlineArgumentsBlock(Emitter, argsInfo, inlineCode, attribute.Constructor).Emit(); } else { if (String.IsNullOrEmpty(customCtor)) { WriteNew(); Write(H5Types.ToJsName(attribute.AttributeType, Emitter)); } else { Write(customCtor); } if (!Emitter.Validator.IsExternalType(type) && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType ? 0 : 1)) { WriteDot(); var name = OverloadsCollection.Create(Emitter, attribute.Constructor).GetOverloadName(); Write(name); } WriteOpenParentheses(); WritePositionalList(attribute.PositionalArguments, attribute); WriteCloseParentheses(); } if (hasInitializer) { WriteComma(); BeginBlock(); var inlineInit = WriteObjectInitializer(attribute.NamedArguments, type, attribute); WriteNewLine(); EndBlock(); if (inlineInit.Count > 0) { Write(", function () "); BeginBlock(); foreach (var init in inlineInit) { Write(init); WriteNewLine(); } EndBlock(); } WriteSpace(); WriteCloseParentheses(); } } }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr?.UserDefinedOperatorMethod; if (method != null) { var inline = Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!Emitter.Validator.IsExternalType(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]; bool isField = left is MemberResolveResult memberTargetrr && 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)) { WriteOpenParentheses(); leftInterfaceTempVar = GetTempVarName(); Write(leftInterfaceTempVar); Write(" = "); binaryOperatorExpression.Left.AcceptVisitor(Emitter); WriteComma(); addClose = true; } var m = FindOperatorTrueOrFalse(left.Type, orElse); Write(H5Types.ToJsName(m.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, m).GetOverloadName()); WriteOpenParentheses(); if (leftInterfaceTempVar != null) { Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(Emitter); } WriteCloseParentheses(); Write(" ? "); if (leftInterfaceTempVar != null) { Write(leftInterfaceTempVar); } else { binaryOperatorExpression.Left.AcceptVisitor(Emitter); } Write(" : "); } if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT; switch (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; } Write(action + "("); } Write(H5Types.ToJsName(method.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { WriteComma(); } else { WriteOpenParentheses(); } if (leftInterfaceTempVar != null) { Write(leftInterfaceTempVar); Write(", "); binaryOperatorExpression.Right.AcceptVisitor(Emitter); } else { new ExpressionListBlock(Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null, null, 0).Emit(); } WriteCloseParentheses(); if (addClose) { WriteCloseParentheses(); } return(true); } } return(false); }