public override void VisitForStatement(ForStatementSyntax node) { // Convert the variable declaration to an assignment expression statement if (node.Declaration != null) { foreach (var variable in node.Declaration.Variables) { // Hoist the variable into a field var symbol = (ILocalSymbol)ModelExtensions.GetDeclaredSymbol(Transformer.Model, variable); var identifier = HoistVariable(new LiftedVariableKey(variable.Identifier, symbol)); if (variable.Initializer != null) { var assignment = identifier.GetReference().Assign((JsExpression)variable.Initializer.Value.Accept(Transformer)); CurrentState.Add(assignment.Express()); } } } else if (node.Initializers.Any()) { foreach (var initializer in node.Initializers) { var assignment = (JsExpression)initializer.Accept(Transformer); CurrentState.Add(assignment.Express()); } } var topOfLoop = GetNextState(); GotoState(topOfLoop); CurrentState = topOfLoop; var afterLoop = GetNextState(); var bodyState = NewState(); var incrementorState = NewState(); var newWhileStatement = Js.While( node.Condition == null ? Js.Primitive(true) : (JsExpression)node.Condition.Accept(Transformer), GotoStateBlock(bodyState)); CurrentState.Add(newWhileStatement); GotoState(afterLoop); CurrentState = bodyState; AcceptStatement(node.Statement, afterLoop, incrementorState); GotoState(incrementorState); CurrentState = incrementorState; foreach (var incrementor in node.Incrementors) { CurrentState.Add(((JsExpression)incrementor.Accept(Transformer)).Express()); } GotoState(topOfLoop); CurrentState = afterLoop; }
protected override void OnBaseStateGenerated() { var lastStatement = CurrentState.Statements.LastOrDefault(); if (lastStatement is JsContinueStatement || lastStatement is JsBreakStatement || lastStatement is JsReturnStatement) { return; } CurrentState.Add(Js.Return(Js.Primitive(false))); }
public override JsNode Visit(JsReturnStatement node) { escapeStatements.Add(new EscapeStatement { Type = Return }); return(Js.Return(Js.Object( Js.Item(EscapeTypeField, Js.Primitive(Return)), Js.Item(EscapeValueField, node.Expression != null ? node.Expression : Js.Null()), Js.Item(EscapeDepthField, Js.Primitive(loopDepth)) ).Compact())); }
public override JsNode Visit(JsBreakStatement node) { escapeStatements.Add(new EscapeStatement { Type = Break, Label = node.Label }); return(Js.Return(Js.Object( Js.Item(EscapeTypeField, Js.Primitive(Break)), Js.Item(EscapeLabelField, node.Label != null ? Js.Primitive(node.Label) : Js.Null()), Js.Item(EscapeDepthField, node.Label != null ? Js.Primitive(transformer.GetLabelDepth(node.Label)) : Js.Primitive(0)) ).Compact())); }
public override void VisitYieldStatement(YieldStatementSyntax node) { var nextState = GetNextState(); if (node.ReturnOrBreakKeyword.IsKind(SyntaxKind.BreakKeyword)) { CurrentState.Add(ChangeState(nextState)); CurrentState.Add(Js.Primitive(false).Return()); } else { CurrentState.Add(ChangeState(nextState)); CurrentState.Add(Js.Reference(stateMachine).Member("set_Current").Invoke((JsExpression)node.Expression.Accept(Transformer)).Express()); CurrentState.Add(Js.Primitive(true).Return()); } CurrentState = nextState; }
public JsStatement GenerateSwitch(State state) { var sections = new List <JsSwitchSection>(); if (state.Parent != null) { var stateSection = Js.Section(Js.Primitive(state.Index)); stateSection.Statements.AddRange(GotoStateStatements(state.Substates.First())); sections.Add(stateSection); } sections.AddRange(state.Substates.Select(substate => { var section = Js.Section(substate.GetAllIndices().Select(index => Js.Primitive(index)).ToArray()); section.Statements.AddRange(substate.Statements); return(section); })); return(state.Wrap(Js.Switch(Js.Reference(BaseStateGenerator.state), sections.ToArray()))); }
public override void VisitYieldStatement(YieldStatementSyntax node) { var nextState = GetNextState(); if (node.ReturnOrBreakKeyword.IsKind(SyntaxKind.BreakKeyword)) { CurrentState.Add(ChangeState(nextState)); CurrentState.Add(Js.Primitive(false).Return()); } else { CurrentState.Add(ChangeState(nextState)); // if (Transformer.Model.Compilation.Assembly.AreAutoPropertiesMinimized()) // CurrentState.Add(Js.Reference(stateMachine).Member("Current").Assign((JsExpression)node.Expression.Accept(Transformer)).Express()); // else CurrentState.Add(Js.Reference(stateMachine).Member("set_Current").Invoke((JsExpression)node.Expression.Accept(Transformer)).Express()); CurrentState.Add(Js.Primitive(true).Return()); } CurrentState = nextState; }
public async Task Compile() { projectName = project.AssemblyName; Compilation compilation = await Profiler.Time("Getting initial project compilation", async() => await project.GetCompilationAsync()); Context.Update(project.Solution, project, compilation, new ReflectionCache(project, compilation)); // If this is the runtime prjoect, declare the array to hold all the GetAssembly functions (this .js file // will be loaded first, and we only want to bother creating the array once.) if (projectName == "mscorlib") { var global = new JsBlockStatement(); jsCompilationUnit.Global = global; var assemblies = Js.Variable(SpecialNames.Assemblies, Js.Array()); global.Local(assemblies); // This ensures that Function.$typeName returns `Function` -- this is important when using // a type function as a generic argument, since otherwise when we try to get a // unique key for the permuatation of type args including a type function, we would get // an empty string for that arg, which would break the cache. jsCompilationUnit.Body.Assign(Js.Reference("Function").Member(SpecialNames.TypeName), Js.Primitive("Function")); } // Declare assembly variable var assemblyVariable = Js.Variable("$" + projectName.MaskSpecialCharacters() + "$Assembly", Js.Null()); jsCompilationUnit.Body.Local(assemblyVariable); // Declare array to store all anonymous types var anonymousTypes = Js.Variable(compilation.Assembly.GetAssemblyAnonymousTypesArray(), Js.Array()); jsCompilationUnit.Body.Local(anonymousTypes); // Declare array to store all the type functions in the assembly var assemblyTypes = Js.Variable(compilation.Assembly.GetAssemblyTypesArray(), Js.Array()); jsCompilationUnit.Body.Local(assemblyTypes); // Build $GetAssemblyMethod, which lazily creates a new Assembly instance var globalIdioms = new Idioms(null); var getAssembly = Js.Function(); getAssembly.Body.If( assemblyVariable.GetReference().EqualTo(Js.Null()), assemblyVariable.GetReference().Assign(globalIdioms.CreateAssembly(compilation.Assembly, assemblyTypes.GetReference())) ); getAssembly.Body.Return(assemblyVariable.GetReference()); jsCompilationUnit.Body.Assign( Js.Reference(compilation.Assembly.GetAssemblyMethodName()), getAssembly); // Declare $assembly variable jsCompilationUnit.Body.Local(SpecialNames.Assembly, Js.Reference(compilation.Assembly.GetAssemblyMethodName())); jsCompilationUnit.Body.Assign(Js.Reference(SpecialNames.Assembly).Member(SpecialNames.AssemblyTypesArray), assemblyTypes.GetReference()); // Add $GetAssemblyMethod to global assemblies array jsCompilationUnit.Body.Express(Js.Reference(SpecialNames.Assemblies).Member("push").Invoke(Js.Reference(SpecialNames.Assembly))); // Builds out all the namespace objects. Types live inside namepsaces, which are represented as // nested Javascript objects. For example, System.Text.StringBuilder is represented (in part) as: // // System = {}; // System.Text = {}; // System.Text.StringBuilder = function() { ... } // // This allows access to classes using dot notation in the expected way. Profiler.Time("Transforming namespaces", () => { var namespaceTransformer = new NamespaceTransformer(jsCompilationUnit.Body); foreach (var syntaxTree in compilation.SyntaxTrees) { var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); compilationUnit.Accept(namespaceTransformer); } }); var actions = new List <Tuple <INamedTypeSymbol, Action> >(); Profiler.Time("Get diagnostics", () => { var diagnostics = compilation.GetDiagnostics(); foreach (var diagnostic in diagnostics) { if (diagnostic.Severity == DiagnosticSeverity.Error) { Console.WriteLine("// " + diagnostic); } } }); // Check for partial classes Profiler.Time("Reassemble partial classes", () => { var partialClassReassembler = new PartialClassReassembler(project, compilation); compilation = partialClassReassembler.UnifyPartialTypes(); }); /* * // Write out all type functions in inheritance order. This allows for complex references between types and * // nested types. * Profiler.Time("Write out type function declarations", () => * { * var allTypeDeclarations = new List<INamedTypeSymbol>(); * foreach (var syntaxTree in compilation.SyntaxTrees) * { * var semanticModel = compilation.GetSemanticModel(syntaxTree); * var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); * var typeDeclarations = GetTypeDeclarations(compilationUnit); * var types = typeDeclarations.Select(x => semanticModel.GetDeclaredSymbol(x)).ToArray(); * allTypeDeclarations.AddRange(types); * } * SweepSort(allTypeDeclarations, x => x); * * jsCompilationUnit.Body.Express(Js.Reference(Context.Instance.SymbolNames[classType.ContainingNamespace, classType.ContainingNamespace.GetFullName()]).Member(classType.GetShortTypeName()), * Js.Reference(SpecialNames.Define).Invoke(Js.Primitive(displayName), baseType)); * jsCompilationUnit.Assign(Js.Reference(Context.Instance.SymbolNames[classType.ContainingNamespace, classType.ContainingNamespace.GetFullName()]).Member(classType.GetShortTypeName()), * Js.Reference(SpecialNames.Define).Invoke(Js.Primitive(displayName), baseType)); * }); */ // Scan all syntax trees for anonymous type creation expressions. We transform them into class // declarations with a series of auto implemented properties. Profiler.Time("Running AnonymousTypeTransformer", () => { var anonymousTypeTransformer = new AnonymousTypeTransformer(jsCompilationUnit.Body, actions); foreach (var syntaxTree in compilation.SyntaxTrees) { var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); compilationUnit.Accept(anonymousTypeTransformer); } }); // Iterate through all the syntax trees and add entries into `actions` that correspond to type // declarations. Profiler.Time("Preparing for core transformation process", () => { foreach (var syntaxTree in compilation.SyntaxTrees) { var semanticModel = compilation.GetSemanticModel(syntaxTree); var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); var transformer = new JsTransformer(syntaxTree, semanticModel, jsCompilationUnit); var typeCollector = new TypeCollector(); compilationUnit.Accept(typeCollector); var typeDeclarations = typeCollector.TypeDeclarations.Where(x => x.GetContainingTypeDeclaration() == null); var delegateDeclarations = typeCollector.DelegateDeclarations.Where(x => x.GetContainingTypeDeclaration() == null); foreach (var type in typeDeclarations) { var _type = type; var typeSymbol = semanticModel.GetDeclaredSymbol(type); Action action = () => { var statements = (JsBlockStatement)_type.Accept(transformer); jsCompilationUnit.Body.Aggregate(statements); }; actions.Add(Tuple.Create(typeSymbol, action)); } foreach (var type in delegateDeclarations) { var _type = type; Action action = () => { var statements = (JsBlockStatement)_type.Accept(transformer); jsCompilationUnit.Body.Aggregate(statements); }; actions.Add(Tuple.Create((INamedTypeSymbol)ModelExtensions.GetDeclaredSymbol(semanticModel, type), action)); } } }); // Sort all the type declarations such that base types always come before subtypes. Profiler.Time("Sorting transformers", () => SweepSort(actions, x => x.Item1)); var transformationActions = actions.Select(x => x.Item2).ToArray(); Profiler.Time("Applying core transformation", () => { foreach (var item in transformationActions) { item(); } }); // Create cultures based on installed .NET cultures. Presumably this is the same regardless // of the platform that compiled this assembly. Only do this for the standard library. if (projectName == "mscorlib" && !Context.Instance.Compilation.Assembly.IsCultureInfoExportDisabled()) { foreach (var culture in CultureInfo.GetCultures(CultureTypes.AllCultures)) { JsExpression target = new JsVariableReferenceExpression(Context.Instance.CultureInfo.GetTypeName()).Invoke().Member("RegisterCulture"); jsCompilationUnit.Body.Add(target.Invoke(new[] { Js.Literal(culture.Name), Js.Literal(culture.DateTimeFormat.ShortDatePattern), Js.Literal(culture.DateTimeFormat.LongDatePattern), Js.Literal(culture.DateTimeFormat.ShortTimePattern), Js.Literal(culture.DateTimeFormat.LongTimePattern), Js.Literal(culture.DateTimeFormat.FullDateTimePattern), Js.Literal(culture.DateTimeFormat.YearMonthPattern), Js.Array(culture.DateTimeFormat.MonthNames.Select(x => Js.Literal(x)).ToArray()), Js.Array(culture.DateTimeFormat.AbbreviatedMonthNames.Select(x => Js.Literal(x)).ToArray()), Js.Array(culture.DateTimeFormat.DayNames.Select(x => Js.Literal(x)).ToArray()) }).Express()); } } // If the project type is a console application, then invoke the Main method at the very // end of the file. var entryPoint = Context.Instance.Compilation.GetEntryPoint(CancellationToken.None); if (entryPoint != null) { jsCompilationUnit.Body.Express(globalIdioms.InvokeStatic(entryPoint)); } // Test minification // var minifier = new JsMinifier(); // jsCompilationUnit.Accept(minifier); }
private JsStatement TransformBody(JsStatement body) { var block = body is JsBlockStatement ? (JsBlockStatement)body : Js.Block(body); if (!escapeStatements.Any()) { return(Js.Express(idioms.Wrap(block))); } else { if (!(block.Statements.Last() is JsReturnStatement)) { block.Return(Js.Object(Js.Item(EscapeTypeField, Js.Primitive(0))).Compact()); } var wrapped = idioms.Wrap(block); var outerBlock = new JsBlockStatement(); var loopResult = outerBlock.Local("$loopResult", wrapped); if (escapeStatements.Any(x => x.Type == Return)) { outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Return)), Js.Return(loopResult.GetReference().Member(EscapeValueField))); } if (escapeStatements.Any(x => x.Type == Continue)) { var escapes = escapeStatements.Where(x => x.Type == Continue).Distinct(); JsStatement ifTrue; if (!escapes.Any(x => x.Label != null)) { ifTrue = Js.Continue(); } else { ifTrue = Js.Switch( loopResult.GetReference().Member(EscapeLabelField), escapes .Where(x => x.Label == null) .Select(x => Js.Section(Js.Null()).Statement(Js.Continue())) .Concat(escapes .Where(x => x.Label != null && transformer.GetLabelDepth(x.Label) == loopDepth) .Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Continue(x.Label)))) .Concat(new[] { Js.Section(Js.DefaultLabel()).Statements(Js.Return(loopResult.GetReference())) }) .ToArray()); } outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Continue)), ifTrue); } if (escapeStatements.Any(x => x.Type == Break)) { var escapes = escapeStatements.Where(x => x.Type == Break).Distinct(); JsStatement ifTrue; if (!escapes.Any(x => x.Label != null)) { ifTrue = Js.Break(); } else { ifTrue = Js.Switch(loopResult.GetReference().Member(EscapeLabelField), escapes.Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Break(x.Label))).ToArray()); } outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Break)), ifTrue); } return(outerBlock); } }
private JsExpression VisitLambdaExpression(ExpressionSyntax node, ParameterSyntax[] parameters, CSharpSyntaxNode body) { var expressionType = (INamedTypeSymbol)model.GetTypeInfo(node).ConvertedType; INamedTypeSymbol delegateType; if (Equals(expressionType.OriginalDefinition, Context.Instance.ExpressionGeneric)) { delegateType = (INamedTypeSymbol)expressionType.TypeArguments[0]; } else { delegateType = expressionType; } var lambdaParameters = parameters.ToArray(); var delegateMethod = (IMethodSymbol)delegateType.GetMembers("Invoke")[0]; // Compiler.CsCompilation.FindType() var lambdaMethods = Context.Instance.Expression.GetMembers("Lambda").OfType <IMethodSymbol>().ToArray(); var lambdaMethods2 = lambdaMethods.Where(x => x.TypeParameters.Count() == 1 && x.Parameters.Count() == 2 && Equals(x.Parameters[0].Type, Context.Instance.Expression) && Equals(x.Parameters[1].Type, Context.Instance.ParameterExpressionArray)).ToArray(); var lambdaMethod = lambdaMethods2.Single(); var parameterMethod = Context.Instance.Expression.GetMembers("Parameter").OfType <IMethodSymbol>().Single(x => x.Parameters.Count() == 2 && Equals(x.Parameters[0].Type, Context.Instance.TypeType) && Equals(x.Parameters[1].Type, Context.Instance.String)); lambdaMethod = lambdaMethod.Construct(delegateType); var jsLambda = idioms.InvokeStatic(lambdaMethod); // Convert parameters var workspace = new JsBlockStatement(); var jsParameters = Js.Array(); for (var i = 0; i < delegateMethod.Parameters.Count(); i++) { var delegateParameter = delegateMethod.Parameters[i]; var lambdaParameter = lambdaParameters[i]; var jsParameter = idioms.InvokeStatic(parameterMethod, idioms.TypeOf(delegateParameter.Type), Js.Primitive(lambdaParameter.Identifier.ToString())); var parameterVariableName = "$lambdaparam$" + lambdaParameter.Identifier; parameterVariables[lambdaParameter.Identifier.ToString()] = parameterVariableName; // Declare a variable to hold the parameter object in the parenthetical's scope workspace.Local(parameterVariableName, jsParameter); // Add a reference to this variable (a ParameterExpression) as one of the // parameters to the lambda. jsParameters.Elements.Add(Js.Reference(parameterVariableName)); } var jsBody = body.Accept(this); jsLambda.AddArgument(jsBody); jsLambda.AddArgument(jsParameters); workspace.Return(jsLambda); return(idioms.Wrap(workspace)); }
public async Task <Tuple <string, Project> > Compile(string projectFile) { var projectFileInfo = new FileInfo(projectFile); var projectFolder = projectFileInfo.Directory.FullName; // These two lines are just a weird hack because you get no files back from compilation.SyntaxTrees // if the user file isn't modified. Not sure why that's happening. var projectUserFile = projectFolder + "\\" + projectFileInfo.Name + ".user"; if (File.Exists(projectUserFile)) { File.SetLastWriteTime(projectUserFile, DateTime.Now); } var project = await MSBuildWorkspace.Create().OpenProjectAsync(projectFile); var projectName = project.AssemblyName; Compilation compilation = await project.GetCompilationAsync(); Context.Update(project.Solution, project, compilation); // Check for yield foreach (var syntaxTree in compilation.SyntaxTrees) { var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); var semanticModel = compilation.GetSemanticModel(syntaxTree); var yieldGenerator = new YieldGenerator(compilation, syntaxTree, semanticModel); compilationUnit = (CompilationUnitSyntax)compilationUnit.Accept(yieldGenerator); compilation = compilation.ReplaceSyntaxTree(syntaxTree, SyntaxFactory.SyntaxTree(compilationUnit, syntaxTree.FilePath)); } compilation = compilation.Clone(); Context.Update(project.Solution, project, compilation); // After the basic transformation happens, we need to fix up some references afterward foreach (var syntaxTree in compilation.SyntaxTrees) { var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); var semanticModel = compilation.GetSemanticModel(syntaxTree); var yieldFixer = new YieldGeneratorFixer(compilation, syntaxTree, semanticModel); compilationUnit = (CompilationUnitSyntax)compilationUnit.Accept(yieldFixer); compilation = compilation.ReplaceSyntaxTree(syntaxTree, SyntaxFactory.SyntaxTree(compilationUnit, syntaxTree.FilePath)); } Context.Update(project.Solution, project, compilation); // Check for async foreach (var syntaxTree in compilation.SyntaxTrees) { var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); var semanticModel = compilation.GetSemanticModel(syntaxTree); var asyncGenerator = new AsyncGenerator(compilation, syntaxTree, semanticModel); compilationUnit = (CompilationUnitSyntax)compilationUnit.Accept(asyncGenerator); compilation = compilation.ReplaceSyntaxTree(syntaxTree, SyntaxFactory.SyntaxTree(compilationUnit, syntaxTree.FilePath)); } Context.Update(project.Solution, project, compilation); var jsCompilationUnit = new JsCompilationUnit { UseStrict = true }; // If this is the runtime prjoect, declare the array to hold all the GetAssembly functions (this .js file // will be loaded first, and we only want to bother creating the array once. if (projectName == "mscorlib") { var assemblies = Js.Variable(SpecialNames.Assemblies, Js.Array()); jsCompilationUnit.Body.Local(assemblies); // This ensures that Function.$typeName returns `Function` -- this is important when using // a type function as a generic argument, since otherwise when we try to assembly a // unique key for the permuatation of type args including a type function, we would get // an empty string for that arg, which would break the cache. jsCompilationUnit.Body.Assign(Js.Reference("Function").Member(SpecialNames.TypeName), Js.Primitive("Function")); } // Declare assembly variable var assemblyVariable = Js.Variable("$" + projectName.MaskSpecialCharacters() + "$Assembly", Js.Null()); jsCompilationUnit.Body.Local(assemblyVariable); // Declare array to store all anonymous types var anonymousTypes = Js.Variable(compilation.Assembly.GetAssemblyAnonymousTypesArray(), Js.Array()); jsCompilationUnit.Body.Local(anonymousTypes); // Declare array to store all the type functions in the assembly var assemblyTypes = Js.Variable(compilation.Assembly.GetAssemblyTypesArray(), Js.Array()); jsCompilationUnit.Body.Local(assemblyTypes); // Build $GetAssemblyMethod, which lazily creates a new Assembly instance var globalIdioms = new Idioms(null); var getAssembly = Js.Function(); getAssembly.Body.If( assemblyVariable.GetReference().EqualTo(Js.Null()), assemblyVariable.GetReference().Assign(globalIdioms.CreateAssembly(compilation.Assembly, assemblyTypes.GetReference())) ); getAssembly.Body.Return(assemblyVariable.GetReference()); jsCompilationUnit.Body.Assign( Js.Reference(compilation.Assembly.GetAssemblyMethodName()), getAssembly); // Add $GetAssemblyMethod to global assemblies array jsCompilationUnit.Body.Express(Js.Reference("$assemblies").Member("push").Invoke(Js.Reference(compilation.Assembly.GetAssemblyMethodName()))); // Builds out all the namespace objects. Types live inside namepsaces, which are represented as // nested Javascript objects. For example, System.Text.StringBuilder is represented (in part) as: // // System = {}; // System.Text = {}; // System.Text.StringBuilder = function() { ... } // // This allows access to classes using dot notation in the expected way. var namespaceTransformer = new NamespaceTransformer(jsCompilationUnit.Body); foreach (var syntaxTree in compilation.SyntaxTrees) { var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); compilationUnit.Accept(namespaceTransformer); } var actions = new List <Tuple <INamedTypeSymbol, Action> >(); // Scan all syntax trees for anonymous type creation expressions. We transform them into class // declarations with a series of auto implemented properties. var anonymousTypeTransformer = new AnonymousTypeTransformer(jsCompilationUnit.Body, actions); foreach (var syntaxTree in compilation.SyntaxTrees) { var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); compilationUnit.Accept(anonymousTypeTransformer); } var diagnostics = compilation.GetDiagnostics(); foreach (var diagnostic in diagnostics) { Console.WriteLine("// " + diagnostic); } // Iterate through all the syntax trees and add entries into `actions` that correspond to type // declarations. foreach (var syntaxTree in compilation.SyntaxTrees) { var semanticModel = compilation.GetSemanticModel(syntaxTree); var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot(); var transformer = new JsTransformer(syntaxTree, semanticModel); var typeDeclarations = GetTypeDeclarations(compilationUnit); foreach (var type in typeDeclarations) { Action action = () => { var statements = (JsBlockStatement)type.Accept(transformer); jsCompilationUnit.Body.Aggregate(statements); }; actions.Add(Tuple.Create((INamedTypeSymbol)ModelExtensions.GetDeclaredSymbol(semanticModel, type), action)); } var delegateDeclarations = GetDelegates(compilationUnit); foreach (var type in delegateDeclarations) { Action action = () => { var statements = (JsBlockStatement)type.Accept(transformer); jsCompilationUnit.Body.Aggregate(statements); }; actions.Add(Tuple.Create((INamedTypeSymbol)ModelExtensions.GetDeclaredSymbol(semanticModel, type), action)); } } // Sort all the type declarations such that base types always come before subtypes. SweepSort(actions); foreach (var item in actions) { item.Item2(); } // If the project type is a console application, then invoke the Main method at the very // end of the file. var entryPoint = compilation.GetEntryPoint(CancellationToken.None); if (entryPoint != null) { jsCompilationUnit.Body.Express(globalIdioms.InvokeStatic(entryPoint)); } // Test minification // var minifier = new JsMinifier(); // jsCompilationUnit.Accept(minifier); // Write out the compiled Javascript file to the target location. var renderer = new JsRenderer(); jsCompilationUnit.Accept(renderer); return(Tuple.Create(renderer.Output, project)); }
public JsStatement ChangeState(State newState) { return(Js.Reference(state).Assign(Js.Primitive(newState.Index)).Express()); }