public abstract void ReportAttributeParameterRequired(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, string parameterName1, string parameterName2);
/// <summary> /// Add another DiagnosticBag to the bag and free the argument. /// </summary> public void AddRangeAndFree(DiagnosticBag bag) { AddRange(bag); bag.Free(); }
public abstract void ReportParameterNotValidForType(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int namedArgumentIndex);
public abstract void ReportMarshalUnmanagedTypeOnlyValidForFields(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int parameterIndex, string unmanagedTypeName, AttributeData attribute);
public abstract void ReportInvalidAttributeArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int parameterIndex, AttributeData attribute);
public abstract void ReportInvalidNamedArgument(DiagnosticBag diagnostics, SyntaxNode attributeSyntax, int namedArgumentIndex, ITypeSymbol attributeClass, string parameterName);
private void ReportOpenFileDiagnostic(DiagnosticBag diagnostics, Exception e) { var messageProvider = _compiler.MessageProvider; diagnostics.Add(messageProvider.CreateDiagnostic(messageProvider.ERR_CantOpenFileWrite, Location.None, _filePath, e.Message)); }
/// <summary> /// Resolves given metadata references to assemblies and modules. /// </summary> /// <param name="compilation">The compilation whose references are being resolved.</param> /// <param name="assemblyReferencesBySimpleName"> /// Used to filter out assemblies that have the same strong or weak identity. /// Maps simple name to a list of identities. The highest version of each name is the first. /// </param> /// <param name="references">List where to store resolved references. References from #r directives will follow references passed to the compilation constructor.</param> /// <param name="boundReferenceDirectiveMap">Maps #r values to successfully resolved metadata references. Does not contain values that failed to resolve.</param> /// <param name="boundReferenceDirectives">Unique metadata references resolved from #r directives.</param> /// <param name="assemblies">List where to store information about resolved assemblies to.</param> /// <param name="modules">List where to store information about resolved modules to.</param> /// <param name="diagnostics">Diagnostic bag where to report resolution errors.</param> /// <returns> /// Maps index to <paramref name="references"/> to an index of a resolved assembly or module in <paramref name="assemblies"/> or <paramref name="modules"/>, respectively. ///</returns> protected ImmutableArray <ResolvedReference> ResolveMetadataReferences( TCompilation compilation, [Out] Dictionary <string, List <ReferencedAssemblyIdentity> > assemblyReferencesBySimpleName, out ImmutableArray <MetadataReference> references, out IDictionary <ValueTuple <string, string>, MetadataReference> boundReferenceDirectiveMap, out ImmutableArray <MetadataReference> boundReferenceDirectives, out ImmutableArray <AssemblyData> assemblies, out ImmutableArray <PEModule> modules, DiagnosticBag diagnostics) { // Locations of all #r directives in the order they are listed in the references list. ImmutableArray <Location> referenceDirectiveLocations; GetCompilationReferences(compilation, diagnostics, out references, out boundReferenceDirectiveMap, out referenceDirectiveLocations); // References originating from #r directives precede references supplied as arguments of the compilation. int referenceCount = references.Length; int referenceDirectiveCount = (referenceDirectiveLocations != null ? referenceDirectiveLocations.Length : 0); var referenceMap = new ResolvedReference[referenceCount]; // Maps references that were added to the reference set (i.e. not filtered out as duplicates) to a set of names that // can be used to alias these references. Duplicate assemblies contribute their aliases into this set. Dictionary <MetadataReference, MergedAliases> lazyAliasMap = null; // Used to filter out duplicate references that reference the same file (resolve to the same full normalized path). var boundReferences = new Dictionary <MetadataReference, MetadataReference>(MetadataReferenceEqualityComparer.Instance); ArrayBuilder <MetadataReference> uniqueDirectiveReferences = (referenceDirectiveLocations != null) ? ArrayBuilder <MetadataReference> .GetInstance() : null; var assembliesBuilder = ArrayBuilder <AssemblyData> .GetInstance(); ArrayBuilder <PEModule> lazyModulesBuilder = null; bool supersedeLowerVersions = compilation.IsSubmission; // When duplicate references with conflicting EmbedInteropTypes flag are encountered, // VB uses the flag from the last one, C# reports an error. We need to enumerate in reverse order // so that we find the one that matters first. for (int referenceIndex = referenceCount - 1; referenceIndex >= 0; referenceIndex--) { var boundReference = references[referenceIndex]; if (boundReference == null) { continue; } // add bound reference if it doesn't exist yet, merging aliases: MetadataReference existingReference; if (boundReferences.TryGetValue(boundReference, out existingReference)) { // merge properties of compilation-based references if the underlying compilations are the same if ((object)boundReference != existingReference) { MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap); } continue; } boundReferences.Add(boundReference, boundReference); Location location; if (referenceIndex < referenceDirectiveCount) { location = referenceDirectiveLocations[referenceIndex]; uniqueDirectiveReferences.Add(boundReference); } else { location = Location.None; } // compilation reference var compilationReference = boundReference as CompilationReference; if (compilationReference != null) { switch (compilationReference.Properties.Kind) { case MetadataImageKind.Assembly: existingReference = TryAddAssembly( compilationReference.Compilation.Assembly.Identity, boundReference, -assembliesBuilder.Count - 1, diagnostics, location, assemblyReferencesBySimpleName, supersedeLowerVersions); if (existingReference != null) { MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap); continue; } // Note, if SourceAssemblySymbol hasn't been created for // compilationAssembly.Compilation yet, we want this to happen // right now. Conveniently, this constructor will trigger creation of the // SourceAssemblySymbol. var asmData = CreateAssemblyDataForCompilation(compilationReference); AddAssembly(asmData, referenceIndex, referenceMap, assembliesBuilder); break; default: throw ExceptionUtilities.UnexpectedValue(compilationReference.Properties.Kind); } continue; } // PE reference var peReference = (PortableExecutableReference)boundReference; Metadata metadata = GetMetadata(peReference, MessageProvider, location, diagnostics); Debug.Assert(metadata != null || diagnostics.HasAnyErrors()); if (metadata != null) { Debug.Assert(metadata != null); switch (peReference.Properties.Kind) { case MetadataImageKind.Assembly: var assemblyMetadata = (AssemblyMetadata)metadata; WeakList <IAssemblySymbol> cachedSymbols = assemblyMetadata.CachedSymbols; if (assemblyMetadata.IsValidAssembly()) { PEAssembly assembly = assemblyMetadata.GetAssembly(); existingReference = TryAddAssembly( assembly.Identity, peReference, -assembliesBuilder.Count - 1, diagnostics, location, assemblyReferencesBySimpleName, supersedeLowerVersions); if (existingReference != null) { MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap); continue; } var asmData = CreateAssemblyDataForFile( assembly, cachedSymbols, peReference.DocumentationProvider, SimpleAssemblyName, compilation.Options.MetadataImportOptions, peReference.Properties.EmbedInteropTypes); AddAssembly(asmData, referenceIndex, referenceMap, assembliesBuilder); } else { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotAssembly, location, peReference.Display)); } // asmData keeps strong ref after this point GC.KeepAlive(assemblyMetadata); break; case MetadataImageKind.Module: var moduleMetadata = (ModuleMetadata)metadata; if (moduleMetadata.Module.IsLinkedModule) { // We don't support netmodules since some checks in the compiler need information from the full PE image // (Machine, Bit32Required, PE image hash). if (!moduleMetadata.Module.IsEntireImageAvailable) { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_LinkedNetmoduleMetadataMustProvideFullPEImage, location, peReference.Display)); } AddModule(moduleMetadata.Module, referenceIndex, referenceMap, ref lazyModulesBuilder); } else { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotModule, location, peReference.Display)); } break; default: throw ExceptionUtilities.UnexpectedValue(peReference.Properties.Kind); } } } if (uniqueDirectiveReferences != null) { uniqueDirectiveReferences.ReverseContents(); boundReferenceDirectives = uniqueDirectiveReferences.ToImmutableAndFree(); } else { boundReferenceDirectives = ImmutableArray <MetadataReference> .Empty; } // We enumerated references in reverse order in the above code // and thus assemblies and modules in the builders are reversed. // Fix up all the indices and reverse the builder content now to get // the ordering matching the references. // // Also fills in aliases. for (int i = 0; i < referenceMap.Length; i++) { if (!referenceMap[i].IsSkipped) { int count = (referenceMap[i].Kind == MetadataImageKind.Assembly) ? assembliesBuilder.Count : lazyModulesBuilder?.Count ?? 0; int reversedIndex = count - 1 - referenceMap[i].Index; referenceMap[i] = GetResolvedReferenceAndFreePropertyMapEntry(references[i], reversedIndex, referenceMap[i].Kind, lazyAliasMap); } } assembliesBuilder.ReverseContents(); assemblies = assembliesBuilder.ToImmutableAndFree(); if (lazyModulesBuilder == null) { modules = ImmutableArray <PEModule> .Empty; } else { lazyModulesBuilder.ReverseContents(); modules = lazyModulesBuilder.ToImmutableAndFree(); } return(ImmutableArray.CreateRange(referenceMap)); }
/// <summary> /// Returns null if an assembly of an equivalent identity has not been added previously, otherwise returns the reference that added it. /// Two identities are considered equivalent if /// - both assembly names are strong (have keys) and are either equal or FX unified /// - both assembly names are weak (no keys) and have the same simple name. /// </summary> private MetadataReference TryAddAssembly( AssemblyIdentity identity, MetadataReference reference, int assemblyIndex, DiagnosticBag diagnostics, Location location, Dictionary <string, List <ReferencedAssemblyIdentity> > referencesBySimpleName, bool supersedeLowerVersions) { var referencedAssembly = new ReferencedAssemblyIdentity(identity, reference, assemblyIndex); List <ReferencedAssemblyIdentity> sameSimpleNameIdentities; if (!referencesBySimpleName.TryGetValue(identity.Name, out sameSimpleNameIdentities)) { referencesBySimpleName.Add(identity.Name, new List <ReferencedAssemblyIdentity> { referencedAssembly }); return(null); } if (supersedeLowerVersions) { foreach (var other in sameSimpleNameIdentities) { if (identity.Version == other.Identity.Version) { return(other.Reference); } } // Keep all versions of the assembly and the first identity in the list the one with the highest version: if (sameSimpleNameIdentities[0].Identity.Version > identity.Version) { sameSimpleNameIdentities.Add(referencedAssembly); } else { sameSimpleNameIdentities.Add(sameSimpleNameIdentities[0]); sameSimpleNameIdentities[0] = referencedAssembly; } return(null); } ReferencedAssemblyIdentity equivalent = default(ReferencedAssemblyIdentity); if (identity.IsStrongName) { foreach (var other in sameSimpleNameIdentities) { // Only compare strong with strong (weak is never equivalent to strong and vice versa). // In order to eliminate duplicate references we need to try to match their identities in both directions since // ReferenceMatchesDefinition is not necessarily symmetric. // (e.g. System.Numerics.Vectors, Version=4.1+ matches System.Numerics.Vectors, Version=4.0, but not the other way around.) if (other.Identity.IsStrongName && IdentityComparer.ReferenceMatchesDefinition(identity, other.Identity) && IdentityComparer.ReferenceMatchesDefinition(other.Identity, identity)) { equivalent = other; break; } } } else { foreach (var other in sameSimpleNameIdentities) { // only compare weak with weak if (!other.Identity.IsStrongName && WeakIdentityPropertiesEquivalent(identity, other.Identity)) { equivalent = other; break; } } } if (equivalent.Identity == null) { sameSimpleNameIdentities.Add(referencedAssembly); return(null); } // equivalent found - ignore and/or report an error: if (identity.IsStrongName) { Debug.Assert(equivalent.Identity.IsStrongName); // versions might have been unified for a Framework assembly: if (identity != equivalent.Identity) { // Dev12 C# reports an error // Dev12 VB keeps both references in the compilation and reports an ambiguity error when a symbol is used. // BREAKING CHANGE in VB: we report an error for both languages // Multiple assemblies with equivalent identity have been imported: '{0}' and '{1}'. Remove one of the duplicate references. MessageProvider.ReportDuplicateMetadataReferenceStrong(diagnostics, location, reference, identity, equivalent.Reference, equivalent.Identity); } // If the versions match exactly we ignore duplicates w/o reporting errors while // Dev12 C# reports: // error CS1703: An assembly with the same identity '{0}' has already been imported. Try removing one of the duplicate references. // Dev12 VB reports: // Fatal error BC2000 : compiler initialization failed unexpectedly: Project already has a reference to assembly System. // A second reference to 'D:\Temp\System.dll' cannot be added. } else { Debug.Assert(!equivalent.Identity.IsStrongName); // Dev12 reports an error for all weak-named assemblies, even if the versions are the same. // We treat assemblies with the same name and version equal even if they don't have a strong name. // This change allows us to de-duplicate #r references based on identities rather than full paths, // and is closer to platforms that don't support strong names and consider name and version enough // to identify an assembly. An identity without version is considered to have version 0.0.0.0. if (identity != equivalent.Identity) { MessageProvider.ReportDuplicateMetadataReferenceWeak(diagnostics, location, reference, identity, equivalent.Reference, equivalent.Identity); } } Debug.Assert(equivalent.Reference != null); return(equivalent.Reference); }
protected void GetCompilationReferences( TCompilation compilation, DiagnosticBag diagnostics, out ImmutableArray <MetadataReference> references, out IDictionary <ValueTuple <string, string>, MetadataReference> boundReferenceDirectives, out ImmutableArray <Location> referenceDirectiveLocations) { boundReferenceDirectives = null; ArrayBuilder <MetadataReference> referencesBuilder = ArrayBuilder <MetadataReference> .GetInstance(); ArrayBuilder <Location> referenceDirectiveLocationsBuilder = null; try { foreach (var referenceDirective in compilation.ReferenceDirectives) { if (compilation.Options.MetadataReferenceResolver == null) { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataReferencesNotSupported, referenceDirective.Location)); break; } // we already successfully bound #r with the same value: if (boundReferenceDirectives != null && boundReferenceDirectives.ContainsKey(ValueTuple.Create(referenceDirective.Location.SourceTree.FilePath, referenceDirective.File))) { continue; } MetadataReference boundReference = ResolveReferenceDirective(referenceDirective.File, referenceDirective.Location, compilation); if (boundReference == null) { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotFound, referenceDirective.Location, referenceDirective.File)); continue; } if (boundReferenceDirectives == null) { boundReferenceDirectives = new Dictionary <ValueTuple <string, string>, MetadataReference>(); referenceDirectiveLocationsBuilder = ArrayBuilder <Location> .GetInstance(); } referencesBuilder.Add(boundReference); referenceDirectiveLocationsBuilder.Add(referenceDirective.Location); boundReferenceDirectives.Add(ValueTuple.Create(referenceDirective.Location.SourceTree.FilePath, referenceDirective.File), boundReference); } // add external reference at the end, so that they are processed first: referencesBuilder.AddRange(compilation.ExternalReferences); // Add all explicit references of the previous script compilation. var previousScriptCompilation = compilation.ScriptCompilationInfo?.PreviousScriptCompilation; if (previousScriptCompilation != null) { referencesBuilder.AddRange(previousScriptCompilation.GetBoundReferenceManager().ExplicitReferences); } if (boundReferenceDirectives == null) { // no directive references resolved successfully: boundReferenceDirectives = SpecializedCollections.EmptyDictionary <ValueTuple <string, string>, MetadataReference>(); } references = referencesBuilder.ToImmutable(); referenceDirectiveLocations = referenceDirectiveLocationsBuilder?.ToImmutableAndFree() ?? ImmutableArray <Location> .Empty; } finally { // Put this in a finally because we have tests that (intentionally) cause ResolveReferenceDirective to throw and // we don't want to clutter the test output with leak reports. referencesBuilder.Free(); } }
/// <summary> /// Merges aliases of the first observed reference (<paramref name="primaryReference"/>) with aliases specified for an equivalent reference (<paramref name="newReference"/>). /// Empty alias list is considered to be the same as a list containing "global", since in both cases C# allows unqualified access to the symbols. /// </summary> private void MergeReferenceProperties(MetadataReference primaryReference, MetadataReference newReference, DiagnosticBag diagnostics, ref Dictionary <MetadataReference, MergedAliases> lazyAliasMap) { if (!CheckPropertiesConsistency(newReference, primaryReference, diagnostics)) { return; } if (lazyAliasMap == null) { lazyAliasMap = new Dictionary <MetadataReference, MergedAliases>(); } MergedAliases mergedAliases; if (!lazyAliasMap.TryGetValue(primaryReference, out mergedAliases)) { mergedAliases = new MergedAliases(); lazyAliasMap.Add(primaryReference, mergedAliases); mergedAliases.Merge(primaryReference); } mergedAliases.Merge(newReference); }
/// <summary> /// Checks if the properties of <paramref name="duplicateReference"/> are compatible with properties of <paramref name="primaryReference"/>. /// Reports inconsistencies to the given diagnostic bag. /// </summary> /// <returns>True if the properties are compatible and hence merged, false if the duplicate reference should not merge it's properties with primary reference.</returns> protected abstract bool CheckPropertiesConsistency(MetadataReference primaryReference, MetadataReference duplicateReference, DiagnosticBag diagnostics);
/// <summary> /// Creates or gets metadata for PE reference. /// </summary> /// <remarks> /// If any of the following exceptions: <see cref="BadImageFormatException"/>, <see cref="FileNotFoundException"/>, <see cref="IOException"/>, /// are thrown while reading the metadata file, the exception is caught and an appropriate diagnostic stored in <paramref name="diagnostics"/>. /// </remarks> private Metadata GetMetadata(PortableExecutableReference peReference, CommonMessageProvider messageProvider, Location location, DiagnosticBag diagnostics) { Metadata existingMetadata; lock (ObservedMetadata) { if (TryGetObservedMetadata(peReference, diagnostics, out existingMetadata)) { return(existingMetadata); } } Metadata newMetadata; Diagnostic newDiagnostic = null; try { newMetadata = peReference.GetMetadata(); // make sure basic structure of the PE image is valid: var assemblyMetadata = newMetadata as AssemblyMetadata; if (assemblyMetadata != null) { bool dummy = assemblyMetadata.IsValidAssembly(); } else { bool dummy = ((ModuleMetadata)newMetadata).Module.IsLinkedModule; } } catch (Exception e) when(e is BadImageFormatException || e is IOException) { newDiagnostic = PortableExecutableReference.ExceptionToDiagnostic(e, messageProvider, location, peReference.Display, peReference.Properties.Kind); newMetadata = null; } lock (ObservedMetadata) { if (TryGetObservedMetadata(peReference, diagnostics, out existingMetadata)) { return(existingMetadata); } if (newDiagnostic != null) { diagnostics.Add(newDiagnostic); } ObservedMetadata.Add(peReference, (MetadataOrDiagnostic)newMetadata ?? newDiagnostic); return(newMetadata); } }
internal static DiagnosticBag GetInstance() { DiagnosticBag bag = s_poolInstance.Allocate(); return(bag); }
public abstract void ReportDuplicateMetadataReferenceWeak(DiagnosticBag diagnostics, Location location, MetadataReference reference, AssemblyIdentity identity, MetadataReference equivalentReference, AssemblyIdentity equivalentIdentity);
public DebuggerProxy(DiagnosticBag bag) { _bag = bag; }
internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken) { Debug.Assert(!Arguments.IsScriptRunner); cancellationToken.ThrowIfCancellationRequested(); if (Arguments.DisplayLogo) { PrintLogo(consoleOutput); } if (Arguments.DisplayHelp) { PrintHelp(consoleOutput); return(Succeeded); } if (ReportErrors(Arguments.Errors, consoleOutput, errorLogger)) { return(Failed); } var touchedFilesLogger = (Arguments.TouchedFilesPath != null) ? new TouchedFileLogger() : null; Compilation compilation = CreateCompilation(consoleOutput, touchedFilesLogger, errorLogger); if (compilation == null) { return(Failed); } var diagnostics = new List <DiagnosticInfo>(); ImmutableArray <DiagnosticAnalyzer> analyzers; ImmutableArray <SourceGenerator> sourceGenerators; ResolveAnalyzersAndGeneratorsFromArguments(diagnostics, MessageProvider, out analyzers, out sourceGenerators); var additionalTextFiles = ResolveAdditionalFilesFromArguments(diagnostics, MessageProvider, touchedFilesLogger); if (ReportErrors(diagnostics, consoleOutput, errorLogger)) { return(Failed); } bool reportAnalyzer = false; CancellationTokenSource analyzerCts = null; AnalyzerManager analyzerManager = null; AnalyzerDriver analyzerDriver = null; try { // Print the diagnostics produced during the parsing stage and exit if there were any errors. if (ReportErrors(compilation.GetParseDiagnostics(), consoleOutput, errorLogger)) { return(Failed); } if (!sourceGenerators.IsEmpty) { ImmutableArray <Diagnostic> generatorDiagnostics; var trees = compilation.GenerateSource( sourceGenerators, this.Arguments.OutputDirectory, writeToDisk: true, cancellationToken: cancellationToken, diagnostics: out generatorDiagnostics); bool generatorReportedErrors = ReportErrors(generatorDiagnostics, consoleOutput, errorLogger); if (!trees.IsEmpty) { compilation = compilation.AddSyntaxTrees(trees); if (ReportErrors(compilation.GetParseDiagnostics(), consoleOutput, errorLogger)) { return(Failed); } } if (generatorReportedErrors) { return(Failed); } } ConcurrentSet <Diagnostic> analyzerExceptionDiagnostics = null; if (!analyzers.IsEmpty) { analyzerCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); analyzerManager = new AnalyzerManager(); analyzerExceptionDiagnostics = new ConcurrentSet <Diagnostic>(); Action <Diagnostic> addExceptionDiagnostic = diagnostic => analyzerExceptionDiagnostics.Add(diagnostic); var analyzerOptions = new AnalyzerOptions(ImmutableArray <AdditionalText> .CastUp(additionalTextFiles)); analyzerDriver = AnalyzerDriver.CreateAndAttachToCompilation(compilation, analyzers, analyzerOptions, analyzerManager, addExceptionDiagnostic, Arguments.ReportAnalyzer, out compilation, analyzerCts.Token); reportAnalyzer = Arguments.ReportAnalyzer && !analyzers.IsEmpty; } if (ReportErrors(compilation.GetDeclarationDiagnostics(), consoleOutput, errorLogger)) { return(Failed); } cancellationToken.ThrowIfCancellationRequested(); string outputName = GetOutputFileName(compilation, cancellationToken); var finalPeFilePath = Path.Combine(Arguments.OutputDirectory, outputName); var finalPdbFilePath = Arguments.PdbPath ?? Path.ChangeExtension(finalPeFilePath, ".pdb"); var finalXmlFilePath = Arguments.DocumentationPath; var diagnosticBag = DiagnosticBag.GetInstance(); try { // NOTE: Unlike the PDB path, the XML doc path is not embedded in the assembly, so we don't need to pass it to emit. var emitOptions = Arguments.EmitOptions. WithOutputNameOverride(outputName). WithPdbFilePath(finalPdbFilePath); // The PDB path is emitted in it's entirety into the PE. This makes it impossible to have deterministic // builds that occur in different source directories. To enable this we shave all path information from // the PDB when specified by the user. // // This is a temporary work around to allow us to make progress with determinism. The following issue // tracks getting an official solution here. // // https://github.com/dotnet/roslyn/issues/9813 if (Arguments.ParseOptions.Features.ContainsKey("pdb-path-determinism") && !string.IsNullOrEmpty(emitOptions.PdbFilePath)) { emitOptions = emitOptions.WithPdbFilePath(Path.GetFileName(emitOptions.PdbFilePath)); } var moduleBeingBuilt = compilation.CheckOptionsAndCreateModuleBuilder( diagnosticBag, Arguments.ManifestResources, emitOptions, debugEntryPoint: null, testData: null, cancellationToken: cancellationToken); if (moduleBeingBuilt != null) { bool success; try { success = compilation.CompileMethods( moduleBeingBuilt, Arguments.EmitPdb, diagnosticBag, filterOpt: null, cancellationToken: cancellationToken); if (success) { // NOTE: as native compiler does, we generate the documentation file // NOTE: 'in place', replacing the contents of the file if it exists Stream xmlStreamOpt = null; if (finalXmlFilePath != null) { xmlStreamOpt = OpenFile(finalXmlFilePath, consoleOutput, PortableShim.FileMode.OpenOrCreate, PortableShim.FileAccess.Write, PortableShim.FileShare.ReadWriteBitwiseOrDelete); if (xmlStreamOpt == null) { return(Failed); } xmlStreamOpt.SetLength(0); } using (xmlStreamOpt) { IEnumerable <DiagnosticInfo> errors; using (var win32ResourceStreamOpt = GetWin32Resources(Arguments, compilation, out errors)) { if (ReportErrors(errors, consoleOutput, errorLogger)) { return(Failed); } success = compilation.GenerateResourcesAndDocumentationComments( moduleBeingBuilt, xmlStreamOpt, win32ResourceStreamOpt, diagnosticBag, cancellationToken); } // only report unused usings if we have success. if (success) { compilation.ReportUnusedImports(null, diagnosticBag, cancellationToken); } } } compilation.CompleteTrees(null); if (analyzerDriver != null) { // GetDiagnosticsAsync is called after ReportUnusedImports // since that method calls EventQueue.TryComplete. Without // TryComplete, we may miss diagnostics. var hostDiagnostics = analyzerDriver.GetDiagnosticsAsync(compilation).Result; diagnosticBag.AddRange(hostDiagnostics); if (hostDiagnostics.Any(IsReportedError)) { success = false; } } } finally { moduleBeingBuilt.CompilationFinished(); } if (success) { using (var peStreamProvider = new CompilerEmitStreamProvider(this, finalPeFilePath)) using (var pdbStreamProviderOpt = Arguments.EmitPdb ? new CompilerEmitStreamProvider(this, finalPdbFilePath) : null) { success = compilation.SerializeToPeStream( moduleBeingBuilt, peStreamProvider, pdbStreamProviderOpt, testSymWriterFactory: null, diagnostics: diagnosticBag, metadataOnly: emitOptions.EmitMetadataOnly, cancellationToken: cancellationToken); if (success && touchedFilesLogger != null) { if (pdbStreamProviderOpt != null) { touchedFilesLogger.AddWritten(finalPdbFilePath); } touchedFilesLogger.AddWritten(finalPeFilePath); } } } } var compileAndEmitDiagnostics = diagnosticBag.ToReadOnly(); GenerateSqmData(Arguments.CompilationOptions, compileAndEmitDiagnostics); if (ReportErrors(compileAndEmitDiagnostics, consoleOutput, errorLogger)) { return(Failed); } } finally { diagnosticBag.Free(); } cancellationToken.ThrowIfCancellationRequested(); if (analyzerExceptionDiagnostics != null && ReportErrors(analyzerExceptionDiagnostics, consoleOutput, errorLogger)) { return(Failed); } bool errorsReadingAdditionalFiles = false; foreach (var additionalFile in additionalTextFiles) { if (ReportErrors(additionalFile.Diagnostics, consoleOutput, errorLogger)) { errorsReadingAdditionalFiles = true; } } if (errorsReadingAdditionalFiles) { return(Failed); } cancellationToken.ThrowIfCancellationRequested(); if (Arguments.TouchedFilesPath != null) { Debug.Assert(touchedFilesLogger != null); if (finalXmlFilePath != null) { touchedFilesLogger.AddWritten(finalXmlFilePath); } var readStream = OpenFile(Arguments.TouchedFilesPath + ".read", consoleOutput, mode: PortableShim.FileMode.OpenOrCreate); if (readStream == null) { return(Failed); } using (var writer = new StreamWriter(readStream)) { touchedFilesLogger.WriteReadPaths(writer); } var writtenStream = OpenFile(Arguments.TouchedFilesPath + ".write", consoleOutput, mode: PortableShim.FileMode.OpenOrCreate); if (writtenStream == null) { return(Failed); } using (var writer = new StreamWriter(writtenStream)) { touchedFilesLogger.WriteWrittenPaths(writer); } } } finally { // At this point analyzers are already complete in which case this is a no-op. Or they are // still running because the compilation failed before all of the compilation events were // raised. In the latter case the driver, and all its associated state, will be waiting around // for events that are never coming. Cancel now and let the clean up process begin. if (analyzerCts != null) { analyzerCts.Cancel(); if (analyzerManager != null) { // Clear cached analyzer descriptors and unregister exception handlers hooked up to the LocalizableString fields of the associated descriptors. analyzerManager.ClearAnalyzerState(analyzers); } if (reportAnalyzer) { ReportAnalyzerExecutionTime(consoleOutput, analyzerDriver, Culture, compilation.Options.ConcurrentBuild); } } } return(Succeeded); }