Пример #1
0
        // Given a syntax tree from a compilation unit, add/convert the comments
        public CSharpCompilation ConvertCompilation(CSharpCompilation compilation)
        {
            m_compilation = compilation;
            var trees = compilation.SyntaxTrees;

            // Loop over the trees
            foreach (SyntaxTree tree in trees)
            {
                SyntaxTree newTree = ConvertTree(tree);
                compilation = compilation.AddSyntaxTrees(newTree);
            }
            return compilation;
        }
        private static CSharpCompilation Create(
            string assemblyName,
            CSharpCompilationOptions options,
            IEnumerable<SyntaxTree> syntaxTrees,
            IEnumerable<MetadataReference> references,
            CSharpCompilation previousSubmission,
            Type returnType,
            Type hostObjectType,
            bool isSubmission)
        {
            Debug.Assert(options != null);
            CheckAssemblyName(assemblyName);

            var validatedReferences = ValidateReferences<CSharpCompilationReference>(references);
            ValidateSubmissionParameters(previousSubmission, returnType, ref hostObjectType);

            var compilation = new CSharpCompilation(
                assemblyName,
                options,
                validatedReferences,
                ImmutableArray<SyntaxTree>.Empty,
                ImmutableDictionary.Create<SyntaxTree, int>(ReferenceEqualityComparer.Instance),
                ImmutableDictionary.Create<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>>(),
                DeclarationTable.Empty,
                previousSubmission,
                returnType,
                hostObjectType,
                isSubmission,
                referenceManager: null,
                reuseReferenceManager: false);

            if (syntaxTrees != null)
            {
                compilation = compilation.AddSyntaxTrees(syntaxTrees);
            }

            Debug.Assert((object)compilation.lazyAssemblySymbol == null);
            return compilation;
        }
Пример #3
0
 protected virtual CSharpCompilation AddToCompilation(CSharpCompilation compilation, DefaultViewCompilerCodeEmitter emitter, string fileName, string namespaceName, string className)
 {
     var tree = emitter.BuildTree(namespaceName, className, fileName);
     return compilation
         .AddSyntaxTrees(tree)
         .AddReferences(emitter.UsedAssemblies
             .Select(a => assemblyCache.GetAssemblyMetadata(a)));
 }
        private CompileResult BuildIncremental(CompileOptions options)
        {
            var result = new CompileResult();

            _logger.Info("BuildIncremental");
            _options = options;

            // update reference files

            var referenceChanges = _referenceFileList.Update(options.References);
            foreach (var file in referenceChanges.Added)
            {
                _logger.Info("+ {0}", file);
                var reference = CreateReference(file);
                _compilation = _compilation.AddReferences(reference);
                _referenceMap.Add(file, reference);
            }
            foreach (var file in referenceChanges.Changed)
            {
                _logger.Info("* {0}", file);
                var reference = CreateReference(file);
                _compilation = _compilation.RemoveReferences(_referenceMap[file])
                                           .AddReferences(reference);
                _referenceMap[file] = reference;
            }
            foreach (var file in referenceChanges.Removed)
            {
                _logger.Info("- {0}", file);
                _compilation = _compilation.RemoveReferences(_referenceMap[file]);
                _referenceMap.Remove(file);
            }

            // update source files

            var sourceChanges = _sourceFileList.Update(options.Files);
            var parseOption = new CSharpParseOptions(LanguageVersion.CSharp6, DocumentationMode.Parse, SourceCodeKind.Regular, options.Defines);
            foreach (var file in sourceChanges.Added)
            {
                _logger.Info("+ {0}", file);
                var syntaxTree = ParseSource(file, parseOption);
                _compilation = _compilation.AddSyntaxTrees(syntaxTree);
                _sourceMap.Add(file, syntaxTree);
            }
            foreach (var file in sourceChanges.Changed)
            {
                _logger.Info("* {0}", file);
                var syntaxTree = ParseSource(file, parseOption);
                _compilation = _compilation.RemoveSyntaxTrees(_sourceMap[file])
                                           .AddSyntaxTrees(syntaxTree);
                _sourceMap[file] = syntaxTree;
            }
            foreach (var file in sourceChanges.Removed)
            {
                _logger.Info("- {0}", file);
                _compilation = _compilation.RemoveSyntaxTrees(_sourceMap[file]);
                _sourceMap.Remove(file);
            }

            // emit or reuse prebuilt output

            var reusePrebuilt = _outputDllStream != null && (
                (_options.PrebuiltOutputReuse == PrebuiltOutputReuseType.WhenNoChange &&
                 sourceChanges.Empty && referenceChanges.Empty) ||
                (_options.PrebuiltOutputReuse == PrebuiltOutputReuseType.WhenNoSourceChange &&
                 sourceChanges.Empty && referenceChanges.Added.Count == 0 && referenceChanges.Removed.Count == 0));

            if (reusePrebuilt)
            {
                _logger.Info("Reuse prebuilt output");

                // write dll

                var dllFile = Path.Combine(_options.WorkDirectory, _options.Output);
                using (var dllStream = new FileStream(dllFile, FileMode.Create))
                {
                    _outputDllStream.Seek(0L, SeekOrigin.Begin);
                    _outputDllStream.CopyTo(dllStream);
                }

                // write pdb or mdb

                switch (_options.DebugSymbolFile)
                {
                    case DebugSymbolFileType.Pdb:
                        var pdbFile = Path.Combine(_options.WorkDirectory, Path.ChangeExtension(_options.Output, ".pdb"));
                        using (var debugSymbolStream = new FileStream(pdbFile, FileMode.Create))
                        {
                            _outputDebugSymbolStream.Seek(0L, SeekOrigin.Begin);
                            _outputDebugSymbolStream.CopyTo(debugSymbolStream);
                        }
                        break;

                    case DebugSymbolFileType.PdbToMdb:
                    case DebugSymbolFileType.Mdb:
                        var mdbFile = Path.Combine(_options.WorkDirectory, _options.Output + ".mdb");
                        using (var debugSymbolStream = new FileStream(mdbFile, FileMode.Create))
                        {
                            _outputDebugSymbolStream.Seek(0L, SeekOrigin.Begin);
                            _outputDebugSymbolStream.CopyTo(debugSymbolStream);
                        }
                        break;
                }

                result.Succeeded = true;
            }
            else
            {
                _logger.Info("Emit");

                Emit(result);
            }

            return result;
        }
Пример #5
0
        private static CSharpCompilation ApplyProjectInfo(CSharpCompilation compilation, CompilationProjectContext project,
            CSharpParseOptions parseOptions)
        {
            var projectAttributes = new Dictionary<string, string>(StringComparer.Ordinal)
            {
                [typeof(AssemblyTitleAttribute).FullName] = EscapeCharacters(project.Title),
                [typeof(AssemblyDescriptionAttribute).FullName] = EscapeCharacters(project.Description),
                [typeof(AssemblyCopyrightAttribute).FullName] = EscapeCharacters(project.Copyright),
                [typeof(AssemblyFileVersionAttribute).FullName] = EscapeCharacters(project.AssemblyFileVersion.ToString()),
                [typeof(AssemblyVersionAttribute).FullName] = EscapeCharacters(RemovePrereleaseTag(project.Version)),
                [typeof(AssemblyInformationalVersionAttribute).FullName] = EscapeCharacters(project.Version)
            };

            var assemblyAttributes = compilation.Assembly.GetAttributes()
                .Select(assemblyAttribute => assemblyAttribute.AttributeClass.ToString());
            var newAttributes = string.Join(Environment.NewLine, projectAttributes
                .Where(projectAttribute => projectAttribute.Value != null && !assemblyAttributes.Contains(projectAttribute.Key))
                .Select(projectAttribute => $"[assembly:{projectAttribute.Key}(\"{projectAttribute.Value}\")]"));

            if (!string.IsNullOrWhiteSpace(newAttributes))
            {
                compilation = compilation.AddSyntaxTrees(new[]
                {
                    CSharpSyntaxTree.ParseText(newAttributes, parseOptions,
                        path: $"{nameof(ApplyProjectInfo)}.cs",
                        encoding: Encoding.UTF8)
                });
            }

            return compilation;
        }
Пример #6
0
        private static CSharpCompilation ApplyVersionInfo(CSharpCompilation compilation, CompilationProjectContext project,
            CSharpParseOptions parseOptions)
        {
            const string assemblyFileVersionName = "System.Reflection.AssemblyFileVersionAttribute";
            const string assemblyVersionName = "System.Reflection.AssemblyVersionAttribute";
            const string assemblyInformationalVersion = "System.Reflection.AssemblyInformationalVersionAttribute";

            var assemblyAttributes = compilation.Assembly.GetAttributes();

            var foundAssemblyFileVersion = false;
            var foundAssemblyVersion = false;
            var foundAssemblyInformationalVersion = false;

            foreach (var assembly in assemblyAttributes) {
                string attributeName = assembly.AttributeClass.ToString();

                if (string.Equals(attributeName, assemblyFileVersionName, StringComparison.Ordinal)) {
                    foundAssemblyFileVersion = true;
                }
                else if (string.Equals(attributeName, assemblyVersionName, StringComparison.Ordinal)) {
                    foundAssemblyVersion = true;
                }
                else if (string.Equals(attributeName, assemblyInformationalVersion, StringComparison.Ordinal)) {
                    foundAssemblyInformationalVersion = true;
                }
            }

            var versionAttributes = new StringBuilder();
            if (!foundAssemblyFileVersion) {
                versionAttributes.AppendLine($"[assembly:{assemblyFileVersionName}(\"{project.AssemblyFileVersion}\")]");
            }

            if (!foundAssemblyVersion) {
                versionAttributes.AppendLine($"[assembly:{assemblyVersionName}(\"{RemovePrereleaseTag(project.Version)}\")]");
            }

            if (!foundAssemblyInformationalVersion) {
                versionAttributes.AppendLine($"[assembly:{assemblyInformationalVersion}(\"{project.Version}\")]");
            }

            if (versionAttributes.Length != 0) {
                compilation = compilation.AddSyntaxTrees(new[]
                {
                    CSharpSyntaxTree.ParseText(versionAttributes.ToString(), parseOptions)
                });
            }

            return compilation;
        }
Пример #7
0
        private static CSharpCompilation ApplyVersionInfo(CSharpCompilation compilation, Project project,
            CSharpParseOptions parseOptions)
        {
            var emptyVersion = new Version(0, 0, 0, 0);

            // If the assembly version is empty then set the version
            if (compilation.Assembly.Identity.Version == emptyVersion)
            {
                return compilation.AddSyntaxTrees(new[]
                {
                    CSharpSyntaxTree.ParseText("[assembly: System.Reflection.AssemblyVersion(\"" + project.Version.Version + "\")]", parseOptions),
                    CSharpSyntaxTree.ParseText("[assembly: System.Reflection.AssemblyInformationalVersion(\"" + project.Version + "\")]", parseOptions)
                });
            }

            return compilation;
        }
Пример #8
0
        internal static Either<ImmutableArray<MetaError>, ImmutableArray<Output>> GetCompletions(CSharpCompilation compilation, Environment environment, IEnumerable<string> files, Func<string, OutputFileName> createOutputFileName, IEnumerable<Attribute> defaultAttributes)
        {
            var trees = files
                .ToImmutableDictionary(x => x, x => Generator.ParseFile(environment, x));
            var stubTrees = Completers.Values
                .Select(x => x.GetStubs(compilation).With(s => SyntaxFactory.ParseSyntaxTree(s)))
                .Where(x => x != null);
            var compilationWithPrototypes = compilation.AddSyntaxTrees(trees.Values.Concat(stubTrees));
            var symbolToTypeMap = Completers.Keys.ToImmutableDictionary(
                type => compilationWithPrototypes.GetTypeByMetadataName(type.FullName),
                type => type
            );
            //TODO think how not to create new compilations all the time
            //TODO check syntax errors first
            //TODO use rewriters/rewriting rules from already compiled meta assembly
            //TODO generate errors if class is not partial

            var results = files
                    .Select(file => {
                        var tree = trees[file];
                        var model = compilationWithPrototypes.GetSemanticModel(tree);
                        var classSyntaxes = tree.GetRoot().DescendantNodes(x => !(x is ClassDeclarationSyntax)).OfType<ClassDeclarationSyntax>();
                        var treeResults = classSyntaxes
                            .SelectMany(classDeclaration => {
                                var type = model.GetDeclaredSymbol(classDeclaration);
                                return Enumerable.Concat(
                                        model.GetDeclaredSymbol(classDeclaration)
                                            .GetAttributes()
                                            .Select(attributeData => symbolToTypeMap.GetValueOrDefault(attributeData.AttributeClass))
                                            .Where(attributeType => attributeType != null),
                                        defaultAttributes.Select(attribute => attribute.GetType())
                                    )
                                    .Distinct()
                                    .Select(attributeType => Completers[attributeType]);
                            }, (classDeclaration, completer) => new { classDeclaration, completer })
                            .Select(x => {
                                var type = model.GetDeclaredSymbol(x.classDeclaration);
                            //if(x.completer == null)
                            //    return null;
                            var additionalUsings = x.completer.Usings.Select(@using => $"using {@using};"); //TODO use real usings, not string representation, otherwize using X  .  A; causes warning
                            Func<string, string> wrapMembers = val
                                => val.With(s => MetaContextExtensions.WrapMembers(s.Yield(), type.Namespace(), type.Location().GetUsings().Concat(additionalUsings).Distinct()));
                                var completion = x.completer.Complete(model, type);
                                return completion.Transform(
                                    errors => errors.Select(e => Generator.CreateError(message: e.Message, file: Path.GetFullPath(file), span: e.Span)),
                                    value => wrapMembers(value)
                                );
                            })
                            .Where(x => x != null);
                        return treeResults
                            .AggregateEither(
                                left => left.SelectMany(x => x),
                                right => new Output(right.ConcatStringsWithNewLines(), createOutputFileName(file))
                            );
                    });
            return results
                .AggregateEither(
                    left => left
                        .SelectMany(x => x)
                        .ToImmutableArray(),
                    right => right.ToImmutableArray()
                );
        }