Пример #1
0
        public override JsExpression VisitInvocationExpression(InvocationExpressionSyntax node)
        {
            var symbol = model.GetSymbolInfo(node).Symbol;
            var method = (IMethodSymbol)symbol;

            if (method.IsStatic)
            {
                var jsMethodInfo = GetExpressionMethod("Call", Context.Instance.MethodInfo, Context.Instance.ExpressionArray);
                var arguments    = node.ArgumentList.Arguments.Select(x => x.Accept(this)).ToList();
                return(idioms.InvokeStatic(jsMethodInfo, idioms.MemberOf(method), Js.Array(arguments.ToArray())));
            }
            if (method.ContainingType.DelegateInvokeMethod != method)
            {
                var jsMethodInfo = GetExpressionMethod("Call", Context.Instance.Expression, Context.Instance.MethodInfo, Context.Instance.ExpressionArray);
                var methodTarget = ((MemberAccessExpressionSyntax)node.Expression).Expression.Accept(this);
                var arguments    = node.ArgumentList.Arguments.Select(x => x.Accept(this)).ToArray();
                var jsMethod     = idioms.InvokeStatic(jsMethodInfo, methodTarget, idioms.MemberOf(method), idioms.MakeArray(Js.Array(arguments), Context.Instance.ExpressionArray));
                return(jsMethod);
            }
            else
            {
                var jsMethodInfo = GetExpressionMethod("Invoke", Context.Instance.Expression, Context.Instance.ExpressionArray);
                var target       = node.Expression.Accept(this);
                var arguments    = node.ArgumentList.Arguments.Select(x => x.Accept(this)).ToArray();
                return(idioms.InvokeStatic(jsMethodInfo, target, idioms.MakeArray(Js.Array(arguments), Context.Instance.ExpressionArray)));
            }
        }
Пример #2
0
        public override JsExpression VisitElementAccessExpression(ElementAccessExpressionSyntax node)
        {
            var symbol    = model.GetSymbolInfo(node);
            var target    = node.Expression.Accept(this);
            var arguments = node.ArgumentList.Arguments[0].Accept(this);

            if (symbol.Symbol is IPropertySymbol)
            {
                var property     = (IPropertySymbol)symbol.Symbol;
                var propertyInfo = idioms.MemberOf(property);
                var jsMethodInfo = GetExpressionMethod("MakeIndex", Context.Instance.Expression, Context.Instance.PropertyInfo, Context.Instance.EnumerableGeneric.Construct(Context.Instance.Expression));
                return(idioms.InvokeStatic(jsMethodInfo, target, propertyInfo, Js.Array(node.ArgumentList.Arguments.Select(x => x.Accept(this)).ToArray())));
            }
            else
            {
                if (node.ArgumentList.Arguments.Count == 1)
                {
                    var jsMethodInfo = GetExpressionMethod("ArrayIndex", Context.Instance.Expression, Context.Instance.Expression);
                    return(idioms.InvokeStatic(jsMethodInfo, target, node.ArgumentList.Arguments.Single().Accept(this)));
                }
                else
                {
                    var jsMethodInfo = GetExpressionMethod("ArrayIndex", Context.Instance.Expression, Context.Instance.ExpressionArray);
                    return(idioms.InvokeStatic(jsMethodInfo, target, node.ArgumentList.Arguments.Single().Accept(this)));
                }
            }
        }
Пример #3
0
        public override JsExpression VisitObjectCreationExpression(ObjectCreationExpressionSyntax node)
        {
            var constructor   = (IMethodSymbol)model.GetSymbolInfo(node).Symbol;
            var jsConstructor = idioms.MemberOf(constructor);
            var args          = node.ArgumentList == null ? new JsExpression[0] : node.ArgumentList.Arguments.Select(x => x.Accept(this)).ToArray();
            var jsMethodInfo  = GetExpressionMethod("New", Context.Instance.ConstructorInfo, Context.Instance.ExpressionArray);
            var jsMethod      = idioms.InvokeStatic(jsMethodInfo, jsConstructor, Js.Array(args));

            if (node.Initializer != null && node.Initializer.Expressions.Count > 0)
            {
                if (node.Initializer.CSharpKind() == SyntaxKind.ObjectInitializerExpression)
                {
                    var memberInit   = GetExpressionMethod("MemberInit", Context.Instance.NewExpression, Context.Instance.MemberBindingArray);
                    var jsMemberInit = idioms.InvokeStatic(
                        memberInit,
                        jsMethod,
                        idioms.Array(Context.Instance.MemberBindingArray, node.Initializer.Expressions.Select(x => VisitMemberInit((BinaryExpressionSyntax)x)).ToArray()));
                    return(jsMemberInit);
                }
                else
                {
                    var firstItem    = node.Initializer.Expressions.First();
                    var items        = new List <List <ExpressionSyntax> >();
                    var subitemCount = 1;
                    if (firstItem is InitializerExpressionSyntax)
                    {
                        var initializer = (InitializerExpressionSyntax)firstItem;
                        items.AddRange(node.Initializer.Expressions.Select(x => ((InitializerExpressionSyntax)x).Expressions.ToList()));
                        subitemCount = initializer.Expressions.Count;
                    }
                    else
                    {
                        items.AddRange(node.Initializer.Expressions.Select(x => new List <ExpressionSyntax> {
                            x
                        }));
                    }
                    var addMethodInfo          = constructor.ContainingType.GetMembers("Add").OfType <IMethodSymbol>().First(x => x.Parameters.Count() == subitemCount);
                    var addMethod              = idioms.MemberOf(addMethodInfo);
                    var elementInitMethodInfo  = GetExpressionMethod("ElementInit", Context.Instance.MethodInfo, Context.Instance.ExpressionArray);
                    var jsMemberInitMethodInfo = GetExpressionMethod("ListInit", Context.Instance.NewExpression, Context.Instance.ElementInitArray);

                    var jsMemberInitMethod = idioms.InvokeStatic(
                        jsMemberInitMethodInfo,
                        jsMethod,
                        idioms.MakeArray(Js.Array(items
                                                  .Select(x => idioms.InvokeStatic(
                                                              elementInitMethodInfo,
                                                              addMethod,
                                                              idioms.MakeArray(Js.Array(x.Select(y => y.Accept(this)).ToArray()), Context.Instance.ExpressionArray)))
                                                  .ToArray()), Context.Instance.ElementInitArray));
                    return(jsMemberInitMethod);
                }
            }
            else
            {
                return(jsMethod);
            }
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #6
0
        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));
        }