public static MetadataOnlyImage Create(ITemporaryStorageService service, Compilation compilation, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            using (Logger.LogBlock(FunctionId.Workspace_SkeletonAssembly_EmitMetadataOnlyImage, cancellationToken))
            {
                // TODO: make it to use SerializableBytes.WritableStream rather than MemoryStream so that
                //       we don't allocate anything for skeleton assembly.
                using (var stream = SerializableBytes.CreateWritableStream())
                {
                    // note: cloning compilation so we don't retain all the generated symbols after its emitted.
                    // * REVIEW * is cloning clone p2p reference compilation as well?
                    var emitResult = compilation.Clone().Emit(stream, options: s_emitOptions, cancellationToken: cancellationToken);

                    if (emitResult.Success)
                    {
                        var storage = service.CreateTemporaryStreamStorage(cancellationToken);

                        stream.Position = 0;
                        storage.WriteStream(stream, cancellationToken);

                        return new MetadataOnlyImage(storage, compilation.AssemblyName);
                    }
                }
            }

            return Empty;
        }
        /// <summary>
        /// Performs fixup steps on the specified compilation.
        /// </summary>
        private static Compilation PerformSyntaxTreeFixup(Compilation compilation, IEnumerable <DataSourceWrapperInfo> infos)
        {
            var syncObject = new Object();
            var trees      = compilation.SyntaxTrees.ToList();
            var result     = compilation.Clone();

            Parallel.ForEach(trees, tree =>
            {
                var changed = false;

                var semanticModel = default(SemanticModel);
                var oldTree       = (CSharpSyntaxTree)tree;
                var newTree       = (CSharpSyntaxTree)tree;

                var info = infos.Where(x => String.Equals(x.UniqueID.ToString(),
                                                          Path.GetFileNameWithoutExtension(oldTree.FilePath), StringComparison.OrdinalIgnoreCase)).SingleOrDefault();

                if (info == null)
                {
                    return;
                }

                lock (syncObject)
                    semanticModel = result.GetSemanticModel(oldTree, true);

                newTree = RewriteSyntaxTree(oldTree, semanticModel, sm => new FixupExpressionPropertiesRewriter(sm));
                if (newTree != oldTree)
                {
                    lock (syncObject)
                        result = result.ReplaceSyntaxTree(oldTree, newTree);

                    oldTree = newTree;
                    changed = true;
                }

                lock (syncObject)
                    semanticModel = result.GetSemanticModel(oldTree, true);

                newTree = RewriteSyntaxTree(oldTree, semanticModel, sm => new RemoveUnnecessaryDataBindingSetterFieldsRewriter(sm));
                if (newTree != oldTree)
                {
                    lock (syncObject)
                        result = result.ReplaceSyntaxTree(oldTree, newTree);

                    oldTree = newTree;
                    changed = true;
                }

                if (changed)
                {
                    lock (syncObject)
                        info.DataSourceWrapperSourceCode = newTree.ToString();
                }
            });

            return(result);
        }
        // Hand out the same compilation reference for everyone who asks.  Use 
        // WeakReference<Compilation> so that if no one is using the MetadataReference,
        // it can be collected.
        internal static Compilation GetCompilationForMetadataReference(ProjectState projectState, Compilation compilation)
        {
            var weakReference = s_compilationReferenceMap.GetValue(projectState, s_createValue);
            Compilation reference;
            lock (s_guard)
            {
                if (!weakReference.TryGetTarget(out reference))
                {
                    reference = compilation.Clone(); // drop all existing symbols
                    weakReference.SetTarget(reference);
                }
            }

            return reference;
        }
Example #4
0
        public static MetadataOnlyImage Create(Workspace workspace, ITemporaryStorageService service, Compilation compilation, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                workspace.LogTestMessage($"Beginning to create a skeleton assembly for {compilation.AssemblyName}...");

                using (Logger.LogBlock(FunctionId.Workspace_SkeletonAssembly_EmitMetadataOnlyImage, cancellationToken))
                {
                    // TODO: make it to use SerializableBytes.WritableStream rather than MemoryStream so that
                    //       we don't allocate anything for skeleton assembly.
                    using (var stream = SerializableBytes.CreateWritableStream())
                    {
                        // note: cloning compilation so we don't retain all the generated symbols after its emitted.
                        // * REVIEW * is cloning clone p2p reference compilation as well?
                        var emitResult = compilation.Clone().Emit(stream, options: s_emitOptions, cancellationToken: cancellationToken);

                        if (emitResult.Success)
                        {
                            workspace.LogTestMessage($"Successfully emitted a skeleton assembly for {compilation.AssemblyName}");
                            var storage = service.CreateTemporaryStreamStorage(cancellationToken);

                            stream.Position = 0;
                            storage.WriteStream(stream, cancellationToken);

                            return new MetadataOnlyImage(storage, compilation.AssemblyName);
                        }
                        else
                        {
                            workspace.LogTestMessage($"Failed to create a skeleton assembly for {compilation.AssemblyName}:");

                            foreach (var diagnostic in emitResult.Diagnostics)
                            {
                                workspace.LogTestMessage("  " + diagnostic.GetMessage());
                            }
                        }
                    }
                }
            }
            finally
            {
                workspace.LogTestMessage($"Done trying to create a skeleton assembly for {compilation.AssemblyName}");
            }

            return Empty;
        }
Example #5
0
        public Compilation CreateNewCompilation()
        {
            var partialTypesA = scanner.typeDeclarationsBySymbol.Where(x => x.Value.Count > 1).SelectMany(x => x.Value).ToArray();
            var partialTypes  = scanner.typeDeclarationsBySymbol.Where(x => x.Value.Count > 1).ToDictionary(x => x.Key, x => x.Value);

            if (partialTypes.Any())
            {
                foreach (var item in partialTypes)
                {
                    var type           = item.Key;
                    var declarations   = item.Value;
                    var newDeclaration = UnifyDeclarations(type, declarations);

                    // Register the first implementation to be replaced by the fully unified type declaration
                    typeDeclarationReplacements[declarations.First()] = newDeclaration;

                    // Register the remaining types for removal
                    foreach (var removedTypeDeclaration in declarations.Skip(1))
                    {
                        removedTypeDeclarations.Add(removedTypeDeclaration);
                    }
                }

                var rewriter            = new PartialClassRewriter(this);
                var newCompilationUnits = new List <Tuple <SyntaxTree, CompilationUnitSyntax> >();
                foreach (var syntaxTree in compilation.SyntaxTrees)
                {
                    var compilationUnit = (CompilationUnitSyntax)syntaxTree.GetRoot();
                    compilationUnit = (CompilationUnitSyntax)compilationUnit.Accept(rewriter);
                    newCompilationUnits.Add(Tuple.Create(syntaxTree, compilationUnit));
                }
                foreach (var item in newCompilationUnits)
                {
                    compilation = compilation.ReplaceSyntaxTree(item.Item1, SyntaxFactory.SyntaxTree(item.Item2, item.Item1.FilePath));
                }
                Context.Update(project.Solution, project, compilation, new ReflectionCache(project, compilation));
                compilation = compilation.Clone();
            }
            return(compilation);
        }
Example #6
0
        public static Compilation RewriteCompilation(Compilation original, ReplacementDictionary dict_old_to_new)
        {
            Contract.Requires(dict_old_to_new != null);
            Contract.Ensures(Contract.Result <Compilation>() != null);

            Output.WriteLine("Rewriting the compilation");

            var curr = original.Clone();

            Contract.Assume(curr != null);
            foreach (var st in original.SyntaxTrees)
            {
                Dictionary <SyntaxNode, SyntaxNode> subdict;
                if (dict_old_to_new.TryGetValue(st.FilePath, out subdict))
                {
                    var r       = new ReplacerInternal(subdict, original);
                    var newtree = r.Replace(st);
                    if (newtree != st) // did something change?
                    {
                        newtree = AddUsingsContracts(newtree);
                        curr    = curr.ReplaceSyntaxTree(st, SyntaxFactory.SyntaxTree(newtree.GetRoot(), null, st.FilePath));
                        Contract.Assume(curr != null);
                    }
                }
            }
            return(curr);
            //var r = new Replacer(dict_old_to_new, original);
            //foreach (var st in original.SyntaxTrees)
            //{
            //  //var newnode = SyntaxNodeExtensions.ReplaceNodes(st.GetRoot(), dict_old_to_new.Keys, ComputeReplacement);
            //  var newtree = r.Replace(st);
            //  if (newtree != st) // did something change?
            //  {
            //    newtree = AddUsingsContracts(newtree);
            //    curr = curr.ReplaceSyntaxTree(st, newtree);
            //  }
            //}
        }
    public virtual Differences VisitCompilation(Compilation compilation1, Compilation compilation2){
      Differences differences = new Differences(compilation1, compilation2);
      if (compilation1 == null || compilation2 == null){
        if (compilation1 != compilation2) differences.NumberOfDifferences++; else differences.NumberOfSimilarities++;
        return differences;
      }
      Compilation changes = (Compilation)compilation2.Clone();
      Compilation deletions = (Compilation)compilation2.Clone();
      Compilation insertions = (Compilation)compilation2.Clone();

      this.OriginalModule = compilation1.TargetModule;
      this.NewModule = compilation2.TargetModule;

      CompilationUnitList cuChanges, cuDeletions, cuInsertions;
      Differences diff = this.VisitCompilationUnitList(compilation1.CompilationUnits, compilation2.CompilationUnits, out cuChanges, out cuDeletions, out cuInsertions);
      if (diff == null){Debug.Assert(false); return differences;}
      changes.CompilationUnits = cuChanges;
      deletions.CompilationUnits = cuDeletions;
      insertions.CompilationUnits = cuInsertions;
      differences.NumberOfDifferences += diff.NumberOfDifferences;
      differences.NumberOfSimilarities += diff.NumberOfSimilarities;

      if (differences.NumberOfDifferences == 0){
        differences.Changes = null;
        differences.Deletions = null;
        differences.Insertions = null;
      }else{
        differences.Changes = changes;
        differences.Deletions = deletions;
        differences.Insertions = insertions;
      }
      return differences;
    }
 public FullDeclarationState(Compilation declarationCompilation)
     : base(new WeakConstantValueSource<Compilation>(declarationCompilation), declarationCompilation.Clone().RemoveAllReferences())
 {
 }
Example #9
0
 public override Compilation VisitCompilation(Compilation compilation)
 {
     if (compilation == null || compilation.TargetModule == null) return null;
     this.FindTypesToBeDuplicated(compilation.TargetModule.Types);
     return base.VisitCompilation((Compilation)compilation.Clone());
 }
Example #10
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));
        }