public override Compilation?CreateCompilation( TextWriter consoleOutput, TouchedFileLogger touchedFilesLogger, ErrorLogger errorLogger, ImmutableArray <AnalyzerConfigOptionsResult> analyzerConfigOptions, AnalyzerConfigOptionsResult globalConfigOptions) { var parseOptions = Arguments.ParseOptions; // We compute script parse options once so we don't have to do it repeatedly in // case there are many script files. var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); bool hadErrors = false; var sourceFiles = Arguments.SourceFiles; var trees = new SyntaxTree?[sourceFiles.Length]; var normalizedFilePaths = new string[sourceFiles.Length]; var diagnosticBag = DiagnosticBag.GetInstance(); if (Arguments.CompilationOptions.ConcurrentBuild) { Parallel.For(0, sourceFiles.Length, UICultureUtilities.WithCurrentUICulture <int>(i => { try { //NOTE: order of trees is important!! trees[i] = ParseFile( parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], diagnosticBag, out normalizedFilePaths[i]); } catch (Exception e) when(FatalError.Report(e)) { throw ExceptionUtilities.Unreachable; } })); } else { for (int i = 0; i < sourceFiles.Length; i++) { //NOTE: order of trees is important!! trees[i] = ParseFile( parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], diagnosticBag, out normalizedFilePaths[i]); } } // If errors had been reported in ParseFile, while trying to read files, then we should simply exit. if (ReportDiagnostics(diagnosticBag.ToReadOnlyAndFree(), consoleOutput, errorLogger)) { Debug.Assert(hadErrors); return(null); } var diagnostics = new List <DiagnosticInfo>(); var uniqueFilePaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < sourceFiles.Length; i++) { var normalizedFilePath = normalizedFilePaths[i]; Debug.Assert(normalizedFilePath != null); Debug.Assert(sourceFiles[i].IsInputRedirected || PathUtilities.IsAbsolute(normalizedFilePath)); if (!uniqueFilePaths.Add(normalizedFilePath)) { // warning CS2002: Source file '{0}' specified multiple times diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.WRN_FileAlreadyIncluded, Arguments.PrintFullPaths ? normalizedFilePath : _diagnosticFormatter.RelativizeNormalizedPath(normalizedFilePath))); trees[i] = null; } } if (Arguments.TouchedFilesPath != null) { foreach (var path in uniqueFilePaths) { touchedFilesLogger.AddRead(path); } } var assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default; var appConfigPath = this.Arguments.AppConfigPath; if (appConfigPath != null) { try { using (var appConfigStream = new FileStream(appConfigPath, FileMode.Open, FileAccess.Read)) { assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream); } if (touchedFilesLogger != null) { touchedFilesLogger.AddRead(appConfigPath); } } catch (Exception ex) { diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.ERR_CantReadConfigFile, appConfigPath, ex.Message)); } } var xmlFileResolver = new LoggingXmlFileResolver(Arguments.BaseDirectory, touchedFilesLogger); var sourceFileResolver = new LoggingSourceFileResolver(ImmutableArray <string> .Empty, Arguments.BaseDirectory, Arguments.PathMap, touchedFilesLogger); MetadataReferenceResolver referenceDirectiveResolver; var resolvedReferences = ResolveMetadataReferences(diagnostics, touchedFilesLogger, out referenceDirectiveResolver); if (ReportDiagnostics(diagnostics, consoleOutput, errorLogger)) { return(null); } var loggingFileSystem = new LoggingStrongNameFileSystem(touchedFilesLogger, _tempDirectory); var optionsProvider = new CompilerSyntaxTreeOptionsProvider(trees, analyzerConfigOptions, globalConfigOptions); return(CSharpCompilation.Create( Arguments.CompilationName, trees.WhereNotNull(), resolvedReferences, Arguments.CompilationOptions .WithMetadataReferenceResolver(referenceDirectiveResolver) .WithAssemblyIdentityComparer(assemblyIdentityComparer) .WithXmlReferenceResolver(xmlFileResolver) .WithStrongNameProvider(Arguments.GetStrongNameProvider(loggingFileSystem)) .WithSourceReferenceResolver(sourceFileResolver) .WithSyntaxTreeOptionsProvider(optionsProvider))); }
public override Compilation CreateCompilation(TextWriter consoleOutput, TouchedFileLogger touchedFilesLogger, ErrorLogger errorLogger) { var parseOptions = Arguments.ParseOptions; var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); bool hadErrors = false; var sourceFiles = Arguments.SourceFiles; var trees = new SyntaxTree[sourceFiles.Length]; var normalizedFilePaths = new String[sourceFiles.Length]; if (Arguments.CompilationOptions.ConcurrentBuild) { Parallel.For(0, sourceFiles.Length, UICultureUtilities.WithCurrentUICulture <int>(i => { //NOTE: order of trees is important!! trees[i] = ParseFile(consoleOutput, parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], errorLogger, out normalizedFilePaths[i]); })); } else { for (int i = 0; i < sourceFiles.Length; i++) { //NOTE: order of trees is important!! trees[i] = ParseFile(consoleOutput, parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], errorLogger, out normalizedFilePaths[i]); } } // If errors had been reported in ParseFile, while trying to read files, then we should simply exit. if (hadErrors) { return(null); } var diagnostics = new List <DiagnosticInfo>(); var uniqueFilePaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < sourceFiles.Length; i++) { var normalizedFilePath = normalizedFilePaths[i]; Debug.Assert(normalizedFilePath != null); Debug.Assert(PathUtilities.IsAbsolute(normalizedFilePath)); if (!uniqueFilePaths.Add(normalizedFilePath)) { // warning CS2002: Source file '{0}' specified multiple times diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.WRN_FileAlreadyIncluded, Arguments.PrintFullPaths ? normalizedFilePath : _diagnosticFormatter.RelativizeNormalizedPath(normalizedFilePath))); trees[i] = null; } } if (Arguments.TouchedFilesPath != null) { foreach (var path in uniqueFilePaths) { touchedFilesLogger.AddRead(path); } } var assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default; var appConfigPath = this.Arguments.AppConfigPath; if (appConfigPath != null) { try { using (var appConfigStream = new FileStream(appConfigPath, FileMode.Open, FileAccess.Read)) { assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream); } if (touchedFilesLogger != null) { touchedFilesLogger.AddRead(appConfigPath); } } catch (Exception ex) { diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.ERR_CantReadConfigFile, appConfigPath, ex.Message)); } } var metadataProvider = GetMetadataProvider(); var xmlFileResolver = new LoggingXmlFileResolver(Arguments.BaseDirectory, touchedFilesLogger); var sourceFileResolver = new LoggingSourceFileResolver(ImmutableArray <string> .Empty, Arguments.BaseDirectory, touchedFilesLogger); var externalReferenceResolver = GetExternalMetadataResolver(touchedFilesLogger); MetadataFileReferenceResolver referenceDirectiveResolver; var resolvedReferences = ResolveMetadataReferences(externalReferenceResolver, metadataProvider, diagnostics, assemblyIdentityComparer, touchedFilesLogger, out referenceDirectiveResolver); if (ReportErrors(diagnostics, consoleOutput, errorLogger)) { return(null); } var strongNameProvider = new LoggingStrongNameProvider(Arguments.KeyFileSearchPaths, touchedFilesLogger); var compilation = CSharpCompilation.Create( Arguments.CompilationName, trees.WhereNotNull(), resolvedReferences, Arguments.CompilationOptions. WithMetadataReferenceResolver(new AssemblyReferenceResolver(referenceDirectiveResolver, metadataProvider)). WithAssemblyIdentityComparer(assemblyIdentityComparer). WithStrongNameProvider(strongNameProvider). WithXmlReferenceResolver(xmlFileResolver). WithSourceReferenceResolver(sourceFileResolver)); return(compilation); }
internal ImmutableArray <Diagnostic> GetDiagnostics(CompilationStage stage, bool includeEarlierStages, CancellationToken cancellationToken) { var builder = DiagnosticBag.GetInstance(); // Parse if (stage == CompilationStage.Parse || (stage > CompilationStage.Parse && includeEarlierStages)) { var syntaxTrees = this.SyntaxTrees; if (this.Options.ConcurrentBuild) { Parallel.ForEach(syntaxTrees, UICultureUtilities.WithCurrentUICulture <PhpSyntaxTree>(syntaxTree => { builder.AddRange(syntaxTree.GetDiagnostics(cancellationToken)); })); } else { foreach (var syntaxTree in syntaxTrees) { cancellationToken.ThrowIfCancellationRequested(); builder.AddRange(syntaxTree.GetDiagnostics(cancellationToken)); } } } // Declare if (stage == CompilationStage.Declare || stage > CompilationStage.Declare && includeEarlierStages) { // CheckAssemblyName(builder); builder.AddRange(Options.Errors); builder.AddRange(Options.Diagnostics); cancellationToken.ThrowIfCancellationRequested(); // the set of diagnostics related to establishing references. builder.AddRange(GetBoundReferenceManager().Diagnostics); //cancellationToken.ThrowIfCancellationRequested(); try { // TODO: cancellationToken builder.AddRange(this.BindAndAnalyseTask().Result.AsImmutable()); } catch (AggregateException e) when(e.InnerException != null) { // unwrap the aggregate exception, keep original stacktrace System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(e.InnerException).Throw(); } cancellationToken.ThrowIfCancellationRequested(); // resolve entry point this.GetEntryPoint(cancellationToken); // builder.AddRange(_lazyDeclarationDiagnostics?.AsEnumerable() ?? Enumerable.Empty <Diagnostic>()); } cancellationToken.ThrowIfCancellationRequested(); // Compile if (stage == CompilationStage.Compile || stage > CompilationStage.Compile && includeEarlierStages) { var methodBodyDiagnostics = DiagnosticBag.GetInstance(); // TODO: perform compilation and report diagnostics // GetDiagnosticsForAllMethodBodies(methodBodyDiagnostics, cancellationToken); builder.AddRangeAndFree(methodBodyDiagnostics); } // Before returning diagnostics, we filter warnings // to honor the compiler options (e.g., /nowarn, /warnaserror and /warn) and the pragmas. var result = DiagnosticBag.GetInstance(); FilterAndAppendAndFreeDiagnostics(result, ref builder); return(result.ToReadOnlyAndFree <Diagnostic>()); }
internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken) { while (true) { cancellationToken.ThrowIfCancellationRequested(); var incompletePart = _state.NextIncompletePart; switch (incompletePart) { case CompletionPart.NameToMembersMap: { var tmp = GetNameToMembersMap(); } break; case CompletionPart.MembersCompleted: { // ensure relevant imports are complete. foreach (var declaration in _mergedDeclaration.Declarations) { if (locationOpt == null || locationOpt.SourceTree == declaration.SyntaxReference.SyntaxTree) { if (declaration.HasUsings || declaration.HasExternAliases) { this.DeclaringCompilation.GetImports(declaration).Complete(cancellationToken); } } } var members = this.GetMembers(); bool allCompleted = true; if (this.DeclaringCompilation.Options.ConcurrentBuild) { RoslynParallel.For( 0, members.Length, UICultureUtilities.WithCurrentUICulture <int>(i => ForceCompleteMemberByLocation(locationOpt, members[i], cancellationToken)), cancellationToken); foreach (var member in members) { if (!member.HasComplete(CompletionPart.All)) { allCompleted = false; break; } } } else { foreach (var member in members) { ForceCompleteMemberByLocation(locationOpt, member, cancellationToken); allCompleted = allCompleted && member.HasComplete(CompletionPart.All); } } if (allCompleted) { _state.NotePartComplete(CompletionPart.MembersCompleted); break; } else { // NOTE: we're going to kick out of the completion part loop after this, // so not making progress isn't a problem. goto done; } } case CompletionPart.None: return; default: // any other values are completion parts intended for other kinds of symbols _state.NotePartComplete(CompletionPart.All & ~CompletionPart.NamespaceSymbolAll); break; } _state.SpinWaitComplete(incompletePart, cancellationToken); } done: // Don't return until we've seen all of the CompletionParts. This ensures all // diagnostics have been reported (not necessarily on this thread). CompletionPart allParts = (locationOpt == null) ? CompletionPart.NamespaceSymbolAll : CompletionPart.NamespaceSymbolAll & ~CompletionPart.MembersCompleted; _state.SpinWaitComplete(allParts, cancellationToken); }
public override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken) { while (true) { cancellationToken.ThrowIfCancellationRequested(); var incompletePart = _state.NextIncompletePart; if (incompletePart == CompletionPart.Attributes) { GetAttributes(); } else if (incompletePart == CompletionPart.Members) { this.SourceDeclaration.GetMembersByName(); } else if (incompletePart == CompletionPart.MembersCompleted) { // ensure relevant imports are complete. foreach (var declaration in _declaration.Declarations) { if (locationOpt == null || locationOpt.SourceTree == declaration.SyntaxReference.SyntaxTree) { if (declaration.HasUsings || declaration.HasExternAliases) { this.DeclaringCompilation.GetImports(declaration).Complete(cancellationToken); } } } var members = this.GetMembers(); bool allCompleted = true; if (this.DeclaringCompilation.Options.ConcurrentBuild) { var po = cancellationToken.CanBeCanceled ? new ParallelOptions() { CancellationToken = cancellationToken } : LanguageCompilation.DefaultParallelOptions; Parallel.For(0, members.Length, po, UICultureUtilities.WithCurrentUICulture <int>(i => { var member = members[i]; ForceCompleteMemberByLocation(locationOpt, member, cancellationToken); })); foreach (var member in members) { if (!member.HasComplete(CompletionPart.All)) { allCompleted = false; break; } } } else { foreach (var member in members) { ForceCompleteMemberByLocation(locationOpt, member, cancellationToken); allCompleted = allCompleted && member.HasComplete(CompletionPart.All); } } if (allCompleted) { _state.NotePartComplete(CompletionPart.MembersCompleted); } else { // NOTE: we're going to kick out of the completion part loop after this, // so not making progress isn't a problem. goto done; } } else if (incompletePart == CompletionPart.StartBoundNode || incompletePart == CompletionPart.FinishBoundNode) { if (_state.NotePartComplete(CompletionPart.StartBoundNode)) { var diagnostics = DiagnosticBag.GetInstance(); CompleteBoundNode(diagnostics, cancellationToken); var thisThreadCompleted = _state.NotePartComplete(CompletionPart.FinishBoundNode); Debug.Assert(thisThreadCompleted); diagnostics.Free(); } } else if (incompletePart == null) { return; } else { // This assert will trigger if we forgot to handle any of the completion parts Debug.Assert(!CompletionPart.NamespaceSymbolAll.Contains(incompletePart)); // any other values are completion parts intended for other kinds of symbols _state.NotePartComplete(incompletePart); } _state.SpinWaitComplete(incompletePart, cancellationToken); } done: // Don't return until we've seen all of the CompletionParts. This ensures all // diagnostics have been reported (not necessarily on this thread). var allParts = (locationOpt == null) ? CompletionPart.NamespaceSymbolAll : CompletionPart.NamespaceSymbolWithLocationAll; _state.SpinWaitComplete(allParts, cancellationToken); }
public override Compilation CreateCompilation(TextWriter consoleOutput, TouchedFileLogger touchedFilesLogger, ErrorLogger errorLogger) { #if XSHARP var parseOptions = Arguments.ParseOptions.WithOutput(consoleOutput); #else var parseOptions = Arguments.ParseOptions; #endif // We compute script parse options once so we don't have to do it repeatedly in // case there are many script files. var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); bool hadErrors = false; var sourceFiles = Arguments.SourceFiles; var trees = new SyntaxTree[sourceFiles.Length]; var normalizedFilePaths = new string[sourceFiles.Length]; var diagnosticBag = DiagnosticBag.GetInstance(); if (Arguments.CompilationOptions.ConcurrentBuild) { Parallel.For(0, sourceFiles.Length, UICultureUtilities.WithCurrentUICulture <int>(i => { //NOTE: order of trees is important!! trees[i] = ParseFile(parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], diagnosticBag, out normalizedFilePaths[i]); })); } else { for (int i = 0; i < sourceFiles.Length; i++) { //NOTE: order of trees is important!! trees[i] = ParseFile(parseOptions, scriptParseOptions, ref hadErrors, sourceFiles[i], diagnosticBag, out normalizedFilePaths[i]); } } // If errors had been reported in ParseFile, while trying to read files, then we should simply exit. if (hadErrors) { Debug.Assert(diagnosticBag.HasAnyErrors()); ReportErrors(diagnosticBag.ToReadOnlyAndFree(), consoleOutput, errorLogger); return(null); } else { Debug.Assert(diagnosticBag.IsEmptyWithoutResolution); diagnosticBag.Free(); } #if XSHARP var newtree = InternalSyntax.XSharpLanguageParser.ProcessTrees(trees, parseOptions); if (newtree != null) { var newtrees = new SyntaxTree[trees.Length + 1]; Array.Copy(trees, newtrees, trees.Length); newtrees[trees.Length] = newtree; trees = newtrees; } #endif var diagnostics = new List <DiagnosticInfo>(); var uniqueFilePaths = new HashSet <string>(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < sourceFiles.Length; i++) { var normalizedFilePath = normalizedFilePaths[i]; Debug.Assert(normalizedFilePath != null); Debug.Assert(PathUtilities.IsAbsolute(normalizedFilePath)); if (!uniqueFilePaths.Add(normalizedFilePath)) { // warning CS2002: Source file '{0}' specified multiple times diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.WRN_FileAlreadyIncluded, Arguments.PrintFullPaths ? normalizedFilePath : _diagnosticFormatter.RelativizeNormalizedPath(normalizedFilePath))); trees[i] = null; } #if XSHARP else if (parseOptions.PreprocessorOutput && Arguments.TouchedFilesPath != null) { touchedFilesLogger.AddWritten(FileNameUtilities.ChangeExtension(normalizedFilePath, ".ppo")); } #endif } #if XSHARP // Add the names of the header files that we have processed foreach (var tree in trees) { if (tree != null) { if (tree.HasCompilationUnitRoot) { var root = tree.GetCompilationUnitRoot(); foreach (var file in root.IncludedFiles) { uniqueFilePaths.Add(file.Key); } } } } #endif if (Arguments.TouchedFilesPath != null) { foreach (var path in uniqueFilePaths) { touchedFilesLogger.AddRead(path); } } var assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default; var appConfigPath = this.Arguments.AppConfigPath; if (appConfigPath != null) { try { using (var appConfigStream = new FileStream(appConfigPath, FileMode.Open, FileAccess.Read)) { assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream); } if (touchedFilesLogger != null) { touchedFilesLogger.AddRead(appConfigPath); } } catch (Exception ex) { diagnostics.Add(new DiagnosticInfo(MessageProvider, (int)ErrorCode.ERR_CantReadConfigFile, appConfigPath, ex.Message)); } } var xmlFileResolver = new LoggingXmlFileResolver(Arguments.BaseDirectory, touchedFilesLogger); var sourceFileResolver = new LoggingSourceFileResolver(ImmutableArray <string> .Empty, Arguments.BaseDirectory, Arguments.PathMap, touchedFilesLogger); MetadataReferenceResolver referenceDirectiveResolver; var resolvedReferences = ResolveMetadataReferences(diagnostics, touchedFilesLogger, out referenceDirectiveResolver); if (ReportErrors(diagnostics, consoleOutput, errorLogger)) { return(null); } var loggingFileSystem = new LoggingStrongNameFileSystem(touchedFilesLogger); return(CSharpCompilation.Create( Arguments.CompilationName, trees.WhereNotNull(), resolvedReferences, Arguments.CompilationOptions. WithMetadataReferenceResolver(referenceDirectiveResolver). WithAssemblyIdentityComparer(assemblyIdentityComparer). WithXmlReferenceResolver(xmlFileResolver). WithStrongNameProvider(Arguments.GetStrongNameProvider(loggingFileSystem, _tempDirectory)). WithSourceReferenceResolver(sourceFileResolver))); }