protected void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { foreach (var attrSection in methodDeclaration.Attributes) { foreach (var attr in attrSection.Attributes) { var rr = this.Emitter.Resolver.ResolveNode(attr.Type, this.Emitter); if (rr.Type.FullName == "Bridge.ExternalAttribute") { return; } else if (rr.Type.FullName == "Bridge.InitAttribute") { InitPosition initPosition = InitPosition.After; if (attr.HasArgumentList) { if (attr.Arguments.Any()) { var argExpr = attr.Arguments.First(); var argrr = this.Emitter.Resolver.ResolveNode(argExpr, this.Emitter); if (argrr.ConstantValue is int) { initPosition = (InitPosition)argrr.ConstantValue; } } } if (initPosition > 0) { return; } } } } this.EnsureComma(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(methodDeclaration.Parameters, methodDeclaration.Body); var overloads = OverloadsCollection.Create(this.Emitter, methodDeclaration); XmlToJsDoc.EmitComment(this, this.MethodDeclaration); var isEntryPoint = Helpers.IsEntryPointMethod(this.Emitter, this.MethodDeclaration); var member_rr = (MemberResolveResult)this.Emitter.Resolver.ResolveNode(this.MethodDeclaration, this.Emitter); string name = overloads.GetOverloadName(false, null, excludeTypeOnly: OverloadsCollection.ExcludeTypeParameterForDefinition(member_rr)); if (isEntryPoint) { this.Write(JS.Funcs.ENTRY_POINT_NAME); } else { this.Write(name); } this.WriteColon(); this.WriteFunction(); if (isEntryPoint) { this.Write(name); this.WriteSpace(); } else { var nm = Helpers.GetFunctionName(this.Emitter.AssemblyInfo.NamedFunctions, member_rr.Member, this.Emitter); if (nm != null) { this.Write(nm); this.WriteSpace(); } } this.EmitMethodParameters(methodDeclaration.Parameters, methodDeclaration.TypeParameters.Count > 0 && Helpers.IsIgnoreGeneric(methodDeclaration, this.Emitter) ? null : methodDeclaration.TypeParameters, methodDeclaration); this.WriteSpace(); var script = this.Emitter.GetScript(methodDeclaration); if (script == null) { if (YieldBlock.HasYield(methodDeclaration.Body)) { new GeneratorBlock(this.Emitter, methodDeclaration).Emit(); } else if (methodDeclaration.HasModifier(Modifiers.Async) || AsyncBlock.HasGoto(methodDeclaration.Body)) { new AsyncBlock(this.Emitter, methodDeclaration).Emit(); } else { methodDeclaration.Body.AcceptVisitor(this.Emitter); } } else { this.BeginBlock(); this.WriteLines(script); this.EndBlock(); } this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); this.Emitter.Comma = true; }
protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context) { var analyzer = new CaptureAnalyzer(this.Emitter.Resolver.Resolver); analyzer.Analyze(this.Body, this.Parameters.Select(p => p.Name)); var oldLevel = this.Emitter.Level; if (analyzer.UsedVariables.Count == 0) { this.Emitter.Level = 1; } AsyncBlock asyncBlock = null; this.PushLocals(); if (this.IsAsync) { if (context is LambdaExpression) { asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context); } else { asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context); } asyncBlock.InitAsyncBlock(); } var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(parameters, body); bool block = body is BlockStatement; this.Write(""); var savedPos = this.Emitter.Output.Length; var savedThisCount = this.Emitter.ThisRefCounter; this.WriteFunction(); this.EmitMethodParameters(parameters, null, context); this.WriteSpace(); int pos = 0; if (!block && !this.IsAsync) { this.BeginBlock(); pos = this.Emitter.Output.Length; } bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync; if (isSimpleLambda) { this.ConvertParamsToReferences(parameters); var rr = this.Emitter.Resolver.ResolveNode(this.Context, this.Emitter) as LambdaResolveResult; if (rr == null || rr.ReturnType.Kind != TypeKind.Void) { this.WriteReturn(true); } } if (this.IsAsync) { asyncBlock.Emit(true); } else { body.AcceptVisitor(this.Emitter); } if (isSimpleLambda) { this.WriteSemiColon(); } if (!block && !this.IsAsync) { this.WriteNewLine(); this.EndBlock(); } if (!block && !this.IsAsync) { this.EmitTempVars(pos); } if (analyzer.UsedVariables.Count == 0) { var name = "f" + (this.Emitter.NamedFunctions.Count + 1); var code = this.Emitter.Output.ToString().Substring(savedPos); var pair = this.Emitter.NamedFunctions.FirstOrDefault(p => p.Value == code); if (pair.Key != null && pair.Value != null) { name = pair.Key; } else { this.Emitter.NamedFunctions.Add(name, code); } this.Emitter.Output.Remove(savedPos, this.Emitter.Output.Length - savedPos); this.Emitter.Output.Insert(savedPos, "$_." + BridgeTypes.ToJsName(this.Emitter.TypeInfo.Type, this.Emitter, true) + "." + name); this.Emitter.Level = oldLevel; } if (this.Emitter.ThisRefCounter > savedThisCount) { this.Emitter.Output.Insert(savedPos, Bridge.Translator.Emitter.ROOT + "." + Bridge.Translator.Emitter.DELEGATE_BIND + "(this, "); this.WriteCloseParentheses(); } this.PopLocals(); this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); }
protected virtual void EmitLambda(IEnumerable<ParameterDeclaration> parameters, AstNode body, AstNode context) { AsyncBlock asyncBlock = null; this.PushLocals(); if (this.IsAsync) { if (context is LambdaExpression) { asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context); } else { asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context); } asyncBlock.InitAsyncBlock(); } var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(parameters, body); bool block = body is BlockStatement; this.Write(""); var savedPos = this.Emitter.Output.Length; var savedThisCount = this.Emitter.ThisRefCounter; this.WriteFunction(); this.EmitMethodParameters(parameters, context); this.WriteSpace(); if (!block && !this.IsAsync) { this.BeginBlock(); } bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync; if (isSimpleLambda) { this.ConvertParamsToReferences(parameters); this.WriteReturn(true); } if (this.IsAsync) { asyncBlock.Emit(true); } else { body.AcceptVisitor(this.Emitter); } if (isSimpleLambda) { this.WriteSemiColon(); } if (!block && !this.IsAsync) { this.WriteNewLine(); this.EndBlock(); } if (this.Emitter.ThisRefCounter > savedThisCount) { this.Emitter.Output.Insert(savedPos, Bridge.Translator.Emitter.ROOT + "." + Bridge.Translator.Emitter.DELEGATE_BIND + "(this, "); this.WriteCloseParentheses(); } this.PopLocals(); this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); }
protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context) { var rr = this.Emitter.Resolver.ResolveNode(context, this.Emitter); var oldLifting = this.Emitter.ForbidLifting; this.Emitter.ForbidLifting = false; var analyzer = new CaptureAnalyzer(this.Emitter); analyzer.Analyze(this.Body, this.Parameters.Select(p => p.Name)); var oldLevel = this.Emitter.Level; if (analyzer.UsedVariables.Count == 0) { this.Emitter.ResetLevel(); Indent(); } AsyncBlock asyncBlock = null; this.PushLocals(); if (this.IsAsync) { if (context is LambdaExpression) { asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context); } else { asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context); } asyncBlock.InitAsyncBlock(); } var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(parameters, body); bool block = body is BlockStatement; this.Write(""); var savedPos = this.Emitter.Output.Length; var savedThisCount = this.Emitter.ThisRefCounter; var capturedVariables = this.GetCapturedLoopVariables(); if (capturedVariables != null && capturedVariables.Length > 0) { this.Write("(function (" + string.Join(", ", capturedVariables) + ") "); this.BeginBlock(); this.Write("return "); } this.WriteFunction(); this.EmitMethodParameters(parameters, null, context); this.WriteSpace(); int pos = 0; if (!block && !this.IsAsync) { this.BeginBlock(); pos = this.Emitter.Output.Length; } bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync; if (isSimpleLambda) { this.ConvertParamsToReferences(parameters); var lrr = rr as LambdaResolveResult; if (lrr == null || lrr.ReturnType.Kind != TypeKind.Void) { this.WriteReturn(true); } } if (this.IsAsync) { asyncBlock.Emit(true); } else { body.AcceptVisitor(this.Emitter); } if (isSimpleLambda) { this.WriteSemiColon(); } if (!block && !this.IsAsync) { this.WriteNewLine(); this.EndBlock(); } if (!block && !this.IsAsync) { this.EmitTempVars(pos); } if (analyzer.UsedVariables.Count == 0) { if (!this.Emitter.ForbidLifting) { var name = "f" + (this.Emitter.NamedFunctions.Count + 1); var code = this.Emitter.Output.ToString().Substring(savedPos); var pair = this.Emitter.NamedFunctions.FirstOrDefault(p => p.Value == code); if (pair.Key != null && pair.Value != null) { name = pair.Key; } else { this.Emitter.NamedFunctions.Add(name, code); } this.Emitter.Output.Remove(savedPos, this.Emitter.Output.Length - savedPos); this.Emitter.Output.Insert(savedPos, JS.Vars.D_ + "." + BridgeTypes.ToJsName(this.Emitter.TypeInfo.Type, this.Emitter, true) + "." + name); } this.Emitter.ResetLevel(oldLevel); } this.Emitter.ForbidLifting = oldLifting; var methodDeclaration = this.Body.GetParent <MethodDeclaration>(); if (this.Emitter.ThisRefCounter > savedThisCount || this.IsAsync && methodDeclaration != null && !methodDeclaration.HasModifier(Modifiers.Static)) { this.Emitter.Output.Insert(savedPos, JS.Funcs.BRIDGE_BIND + "(this, "); this.WriteCloseParentheses(); } if (capturedVariables != null && capturedVariables.Length > 0) { this.WriteSemiColon(true); this.EndBlock(); this.Write(")(" + string.Join(", ", capturedVariables) + ")"); } this.PopLocals(); this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); }
protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context) { AsyncBlock asyncBlock = null; this.PushLocals(); if (this.IsAsync) { if (context is LambdaExpression) { asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context); } else { asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context); } asyncBlock.InitAsyncBlock(); } var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(parameters, body); bool block = body is BlockStatement; this.Write(""); var savedPos = this.Emitter.Output.Length; var savedThisCount = this.Emitter.ThisRefCounter; this.WriteFunction(); this.EmitMethodParameters(parameters, context); this.WriteSpace(); int pos = 0; if (!block && !this.IsAsync) { this.BeginBlock(); pos = this.Emitter.Output.Length; } bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync; if (isSimpleLambda) { this.ConvertParamsToReferences(parameters); var rr = this.Emitter.Resolver.ResolveNode(this.Context, this.Emitter) as LambdaResolveResult; if (rr == null || rr.ReturnType.Kind != TypeKind.Void) { this.WriteReturn(true); } } if (this.IsAsync) { asyncBlock.Emit(true); } else { body.AcceptVisitor(this.Emitter); } if (isSimpleLambda) { this.WriteSemiColon(); } if (!block && !this.IsAsync) { this.WriteNewLine(); this.EndBlock(); } if (!block && !this.IsAsync) { this.EmitTempVars(pos); } this.PopLocals(); this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); }
protected void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { foreach (var attrSection in methodDeclaration.Attributes) { foreach (var attr in attrSection.Attributes) { var rr = this.Emitter.Resolver.ResolveNode(attr.Type, this.Emitter); if (rr.Type.FullName == "Bridge.ExternalAttribute") { return; } else if (rr.Type.FullName == "Bridge.InitAttribute") { int initPosition = 0; if (attr.HasArgumentList) { if (attr.Arguments.Any()) { var argExpr = attr.Arguments.First(); var argrr = this.Emitter.Resolver.ResolveNode(argExpr, this.Emitter); if (argrr.ConstantValue is int) { initPosition = (int)argrr.ConstantValue; } } } if (initPosition > 0) { return; } } } } this.EnsureComma(); this.ResetLocals(); var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(methodDeclaration.Parameters, methodDeclaration.Body); var overloads = OverloadsCollection.Create(this.Emitter, methodDeclaration); XmlToJsDoc.EmitComment(this, this.MethodDeclaration); string name = overloads.GetOverloadName(false, null, true); if (Helpers.IsEntryPointMethod(this.Emitter, methodDeclaration)) { name = JS.Fields.MAIN; } this.Write(name); this.WriteColon(); this.WriteFunction(); if (this.Emitter.AssemblyInfo.EnableNamedFunctionExpressions) { // If the option enabled then use named function expressions (see #2407) // like doSomething: function doSomething() { } // instead of doSomething: function () { } this.Write(name); } this.EmitMethodParameters(methodDeclaration.Parameters, methodDeclaration.TypeParameters.Count > 0 && Helpers.IsIgnoreGeneric(methodDeclaration, this.Emitter) ? null : methodDeclaration.TypeParameters, methodDeclaration); this.WriteSpace(); var script = this.Emitter.GetScript(methodDeclaration); if (script == null) { if (YieldBlock.HasYield(methodDeclaration.Body)) { new GeneratorBlock(this.Emitter, methodDeclaration).Emit(); } else if (methodDeclaration.HasModifier(Modifiers.Async) || AsyncBlock.HasGoto(methodDeclaration.Body)) { new AsyncBlock(this.Emitter, methodDeclaration).Emit(); } else { methodDeclaration.Body.AcceptVisitor(this.Emitter); } } else { this.BeginBlock(); this.WriteLines(script); this.EndBlock(); } this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); this.Emitter.Comma = true; }
protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context) { AsyncBlock asyncBlock = null; this.PushLocals(); if (this.IsAsync) { if (context is LambdaExpression) { asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context); } else { asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context); } asyncBlock.InitAsyncBlock(); } var prevMap = this.BuildLocalsMap(); var prevNamesMap = this.BuildLocalsNamesMap(); this.AddLocals(parameters, body); bool block = body is BlockStatement; this.Write(""); var savedPos = this.Emitter.Output.Length; var savedThisCount = this.Emitter.ThisRefCounter; this.WriteFunction(); this.EmitMethodParameters(parameters, context); this.WriteSpace(); if (!block && !this.IsAsync) { this.BeginBlock(); } bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync; if (isSimpleLambda) { this.ConvertParamsToReferences(parameters); this.WriteReturn(true); } if (this.IsAsync) { asyncBlock.Emit(true); } else { body.AcceptVisitor(this.Emitter); } if (isSimpleLambda) { this.WriteSemiColon(); } if (!block && !this.IsAsync) { this.WriteNewLine(); this.EndBlock(); } if (this.Emitter.ThisRefCounter > savedThisCount) { this.Emitter.Output.Insert(savedPos, Bridge.Translator.Emitter.ROOT + "." + Bridge.Translator.Emitter.DELEGATE_BIND + "(this, "); this.WriteCloseParentheses(); } this.PopLocals(); this.ClearLocalsMap(prevMap); this.ClearLocalsNamesMap(prevNamesMap); }