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