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))); } }
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))); } } }
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); } }
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 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); }
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)); }