コード例 #1
0
        private async Task <FixResult> FixDiagnosticsAsync(
            string diagnosticId,
            Project project,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            ImmutableArray <CodeFixProvider> fixers,
            CancellationToken cancellationToken)
        {
            ImmutableArray <Diagnostic> previousDiagnostics = ImmutableArray <Diagnostic> .Empty;

            while (true)
            {
                Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                if (!VerifyCompilerDiagnostics(compilation, cancellationToken))
                {
                    return(FixResult.CompilerError);
                }

                var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, DefaultCompilationWithAnalyzersOptions);

                ImmutableArray <Diagnostic> diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

                diagnostics = diagnostics
                              .Where(f => f.Id == diagnosticId && f.Severity != DiagnosticSeverity.Hidden)
                              .ToImmutableArray();

                int length = diagnostics.Length;

                if (length == 0)
                {
                    return(FixResult.Success);
                }

                if (length == previousDiagnostics.Length &&
                    !diagnostics.Except(previousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any())
                {
                    break;
                }

                previousDiagnostics = diagnostics;

                if (Options.BatchSize > 0 &&
                    length > Options.BatchSize)
                {
                    diagnostics = ImmutableArray.CreateRange(diagnostics, 0, Options.BatchSize, f => f);
                }

                await FixDiagnosticsAsync(diagnosticId, project, diagnostics, fixers, cancellationToken).ConfigureAwait(false);

                if (Options.BatchSize <= 0 ||
                    length <= Options.BatchSize)
                {
                    break;
                }

                project = CurrentSolution.GetProject(project.Id);
            }

            return(FixResult.Success);
        }
コード例 #2
0
        private ImmutableArray <Diagnostic> GetDiagnosticsForDocument([NotNull] Document document)
        {
            ImmutableArray <DiagnosticAnalyzer> analyzers = ImmutableArray.Create(CreateAnalyzer());
            Compilation compilation = document.Project.GetCompilationAsync().Result;
            CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(analyzers,
                                                                                          cancellationToken: CancellationToken.None);

            ImmutableArray <Diagnostic> compilerDiagnostics = compilation.GetDiagnostics(CancellationToken.None);

            ValidateCompilerDiagnostics(compilerDiagnostics);

            SyntaxTree tree = document.GetSyntaxTreeAsync().Result;

            ImmutableArray <Diagnostic> .Builder builder = ImmutableArray.CreateBuilder <Diagnostic>();
            foreach (Diagnostic analyzerDiagnostic in compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result)
            {
                Location location = analyzerDiagnostic.Location;
                if (location.IsInSource && location.SourceTree == tree)
                {
                    builder.Add(analyzerDiagnostic);
                }
            }

            return(builder.ToImmutable());
        }
コード例 #3
0
        private ImmutableArray <Diagnostic> GetDiagnostics(string filePath, string csharpSource)
        {
            SyntaxTree tree = CSharpSyntaxTree.ParseText(csharpSource, path: filePath);

            CSharpCompilation compilation = CSharpCompilation.Create("target")
                                            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
                                            .AddSyntaxTrees(tree);

            ImmutableArray <Diagnostic> parseDiagnostics = compilation.GetParseDiagnostics();

            Assembly stylecopAnalyzersAssembly            = Assembly.LoadFile(GetPathToFile(@"StyleCop.Analyzers.dll"));
            ImmutableArray <DiagnosticAnalyzer> analyzers = stylecopAnalyzersAssembly.GetTypes()
                                                            .Where(t => t.IsAbstract == false && typeof(DiagnosticAnalyzer).IsAssignableFrom(t))
                                                            .Select(t => Activator.CreateInstance(t) as DiagnosticAnalyzer)
                                                            .ToImmutableArray();

            CompilationWithAnalyzersOptions options = new CompilationWithAnalyzersOptions(
                new AnalyzerOptions(default(ImmutableArray <AdditionalText>)), OnAnalyzerException, false, false);

            CompilationWithAnalyzers compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, options);

            Task <ImmutableArray <Diagnostic> > analyzerDiagnosticsTask = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();

            analyzerDiagnosticsTask.Wait();
            ImmutableArray <Diagnostic> analyzerDiagnostics = analyzerDiagnosticsTask.Result;

            return(parseDiagnostics.Concat(analyzerDiagnostics).ToImmutableArray());
        }
コード例 #4
0
        private static async Task Main(string[] args)
        {
            string solutionPath = args[0];

            MSBuildWorkspace workspace = MSBuildWorkspace.Create();
            Solution         solution  = await workspace.OpenSolutionAsync(solutionPath).ConfigureAwait(false);

            SealedAnalyzer analyzer = new SealedAnalyzer();
            ImmutableArray <DiagnosticAnalyzer> analyzers = ImmutableArray.Create <DiagnosticAnalyzer>(analyzer);

            foreach (Project project in solution.Projects)
            {
                Compilation compilation = await project.GetCompilationAsync().ConfigureAwait(false);

                CompilationWithAnalyzers    compilationWithAnalyzers = compilation.WithAnalyzers(analyzers);
                ImmutableArray <Diagnostic> analyzerDiagnostics      = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false);

                PrintDiagnostics(analyzerDiagnostics);

                void PrintDiagnostics(ImmutableArray <Diagnostic> diagnostics)
                {
                    if (diagnostics.Length > 0)
                    {
                        System.Console.WriteLine("----------------------------------------");
                        System.Console.WriteLine($"{project.Name}: {diagnostics.Length} diagnostics");
                        foreach (Diagnostic diagnostic in diagnostics)
                        {
                            System.Console.Write("\t");
                            System.Console.WriteLine(diagnostic);
                        }
                    }
                }
            }
        }
コード例 #5
0
        public async Task <Diagnostic[]> GetDiagnosticsAsync(string path)
        {
            string source     = File.ReadAllText(path);
            var    syntaxTree = CSharpSyntaxTree.ParseText(source);

            var baseCompilation = CSharpCompilation.Create(
                "analyzer-output",
                new[] { syntaxTree },
                new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) },
                new CSharpCompilationOptions(OutputKind.NetModule)
                );

            var analyzers = AnalyzerTypes.Select(Activator.CreateInstance)
                            .Cast <DiagnosticAnalyzer>()
                            .ToArray();

            var compilation = new CompilationWithAnalyzers(
                baseCompilation,
                ImmutableArray.Create(analyzers),
                new AnalyzerOptions(ImmutableArray.Create <AdditionalText>()),
                CancellationToken.None
                );

            ImmutableArray <Diagnostic> diagnostics = await compilation.GetAnalyzerDiagnosticsAsync();

            return(diagnostics.ToArray());
        }
コード例 #6
0
        protected Diagnostic[] GetDiagnostics(IEnumerable <string> sourceCodes)
        {
            DiagnosticAnalyzer       analyzer = GetDiagnosticAnalyzer();
            Project                  project  = CreateProject(sourceCodes);
            CompilationWithAnalyzers compilationWithAnalyzers = project.GetCompilationAsync().Result
                                                                .WithAnalyzers(ImmutableArray.Create(analyzer));
            ImmutableArray <Diagnostic> analyzerDiagnostics = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result;
            List <Diagnostic>           diagnostics         = new List <Diagnostic>(analyzerDiagnostics.Length);

            foreach (Diagnostic diagnostic in analyzerDiagnostics)
            {
                if (diagnostic.Location == Location.None || diagnostic.Location.IsInMetadata)
                {
                    diagnostics.Add(diagnostic);
                }
                else
                {
                    SyntaxTree tree;
                    foreach (Document doc in project.Documents)
                    {
                        tree = doc.GetSyntaxTreeAsync().Result;
                        if (tree == diagnostic.Location.SourceTree)
                        {
                            diagnostics.Add(diagnostic);
                        }
                    }
                }
            }

            return(diagnostics.OrderBy(d => d.Location.SourceSpan.Start).ToArray());
        }
コード例 #7
0
        public static Task <ImmutableArray <Diagnostic> > GetAnalyzerDiagnosticsAsync(
            this Compilation compilation,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            CompilationWithAnalyzersOptions analysisOptions,
            CancellationToken cancellationToken = default)
        {
            var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, analysisOptions);

            return(compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken));
        }
コード例 #8
0
        private async Task FormatWithAnalyzersCoreAsync(Workspace workspace, ProjectId projectId, IEnumerable <DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken)
        {
            if (analyzers != null && analyzers.Count() != 0)
            {
                var project     = workspace.CurrentSolution.GetProject(projectId);
                var diagnostics = await GetDiagnostics(project, analyzers, cancellationToken).ConfigureAwait(false);

                // Ensure at least 1 analyzer supporting the current project's language ran
                if (_compilationWithAnalyzers != null)
                {
                    var extension  = StringComparer.OrdinalIgnoreCase.Equals(project.Language, "C#") ? ".csproj" : ".vbproj";
                    var resultFile = project.FilePath?.Substring(project.FilePath.LastIndexOf(Path.DirectorySeparatorChar)).Replace(extension, "_CodeFormatterResults.txt");

                    foreach (var analyzer in analyzers)
                    {
                        var diags = await _compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(ImmutableArray.Create(analyzer), cancellationToken);

                        if (Verbose || LogOutputPath != null)
                        {
                            var analyzerTelemetryInfo = await _compilationWithAnalyzers.GetAnalyzerTelemetryInfoAsync(analyzer, cancellationToken);

                            FormatLogger.WriteLine("{0}\t{1}\t{2}\t{3}", project.Name, analyzer.ToString(), diags.Count(), analyzerTelemetryInfo.ExecutionTime);
                            var resultPath = Path.ChangeExtension(LogOutputPath + resultFile, "json");
                            LogDiagnostics(resultPath, diags);
                        }
                    }
                }

                if (ApplyFixes)
                {
                    var batchFixer = WellKnownFixAllProviders.BatchFixer;
                    var context    = new FixAllContext(
                        project.Documents.First(), // TODO: Shouldn't this be the whole project?
                        new UberCodeFixer(_diagnosticIdToFixerMap),
                        FixAllScope.Project,
                        null,
                        diagnostics.Select(d => d.Id),
                        new FormattingEngineDiagnosticProvider(project, diagnostics),
                        cancellationToken);

                    var fix = await batchFixer.GetFixAsync(context).ConfigureAwait(false);

                    if (fix != null)
                    {
                        foreach (var operation in await fix.GetOperationsAsync(cancellationToken).ConfigureAwait(false))
                        {
                            operation.Apply(workspace, cancellationToken);
                        }
                    }
                }
            }
        }
コード例 #9
0
        public static async Task <ImmutableDictionary <DiagnosticAnalyzer, AnalysisResult> > AnalyzeAsync(this CompilationWithAnalyzers analyzerDriver, Project project, CancellationToken cancellationToken)
        {
            var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

            // Run all analyzers at once.
            // REVIEW: why there are 2 different cancellation token? one that I can give to constructor and one I can give in to each method?
            // REVIEW: we drop all those allocations for the diagnostics returned. can we avoid this?
            await analyzerDriver.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

            // this is wierd, but now we iterate through each analyzer for each tree to get cached result.
            // REVIEW: no better way to do this?
            var noSpanFilter = default(TextSpan?);
            var analyzers    = analyzerDriver.Analyzers;
            var compilation  = analyzerDriver.Compilation;

            var builder = ImmutableDictionary.CreateBuilder <DiagnosticAnalyzer, AnalysisResult>();

            foreach (var analyzer in analyzers)
            {
                var result = new Builder(project, version);

                // REVIEW: more unnecessary allocations just to get diagnostics per analyzer
                var oneAnalyzers = ImmutableArray.Create(analyzer);

                foreach (var tree in compilation.SyntaxTrees)
                {
                    var model = compilation.GetSemanticModel(tree);

                    var syntax = await analyzerDriver.GetAnalyzerSyntaxDiagnosticsAsync(tree, oneAnalyzers, cancellationToken).ConfigureAwait(false);

                    Contract.Requires(syntax.Count() == CompilationWithAnalyzers.GetEffectiveDiagnostics(syntax, analyzerDriver.Compilation).Count());
                    result.AddSyntaxDiagnostics(tree, syntax);

                    var semantic = await analyzerDriver.GetAnalyzerSemanticDiagnosticsAsync(model, noSpanFilter, oneAnalyzers, cancellationToken).ConfigureAwait(false);

                    Contract.Requires(semantic.Count() == CompilationWithAnalyzers.GetEffectiveDiagnostics(semantic, analyzerDriver.Compilation).Count());
                    result.AddSemanticDiagnostics(tree, semantic);
                }

                var rest = await analyzerDriver.GetAnalyzerCompilationDiagnosticsAsync(oneAnalyzers, cancellationToken).ConfigureAwait(false);

                Contract.Requires(rest.Count() == CompilationWithAnalyzers.GetEffectiveDiagnostics(rest, analyzerDriver.Compilation).Count());
                result.AddCompilationDiagnostics(rest);

                builder.Add(analyzer, result.ToResult());
            }

            return(builder.ToImmutable());
        }
コード例 #10
0
        private static IEnumerable <Diagnostic> EnumerateAnalyzerDiagnostics(
            [NotNull] CompilationWithAnalyzers compilationWithAnalyzers, [NotNull] SyntaxTree tree,
            DiagnosticsCaptureMode diagnosticsCaptureMode)
        {
            foreach (Diagnostic analyzerDiagnostic in compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result)
            {
                Location location = analyzerDiagnostic.Location;

                if (diagnosticsCaptureMode == DiagnosticsCaptureMode.AllowOutsideSourceTree ||
                    LocationIsInSourceTree(location, tree))
                {
                    yield return(analyzerDiagnostic);
                }
            }
        }
コード例 #11
0
        public IEnumerable <Diagnostic> GetDiagnostics(Compilation compilation)
        {
            if (diagnosticAnalyzers.IsDefaultOrEmpty)
            {
                return(new Diagnostic[0]);
            }

            using (var tokenSource = new CancellationTokenSource())
            {
                var compilationWithAnalyzer = new CompilationWithAnalyzers(compilation, diagnosticAnalyzers, null,
                                                                           tokenSource.Token);

                return(compilationWithAnalyzer.GetAnalyzerDiagnosticsAsync().Result);
            }
        }
コード例 #12
0
        public static async Task <ImmutableArray <Diagnostic> > GetAnalyzerDiagnosticsAsync(
            this Compilation compilation,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            IComparer <Diagnostic> comparer     = null,
            CancellationToken cancellationToken = default)
        {
            CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, default(AnalyzerOptions), cancellationToken);

            ImmutableArray <Diagnostic> diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken);

            if (comparer != null)
            {
                diagnostics = diagnostics.Sort(comparer);
            }

            return(diagnostics);
        }
コード例 #13
0
        public static async Task <ImmutableArray <Diagnostic> > GetAnalyzerDiagnosticsAsync(
            this Compilation compilation,
            DiagnosticAnalyzer analyzer,
            IComparer <Diagnostic> comparer     = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create(analyzer), default(AnalyzerOptions), cancellationToken);

            ImmutableArray <Diagnostic> diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

            if (comparer != null)
            {
                diagnostics = diagnostics.Sort(comparer);
            }

            return(diagnostics);
        }
コード例 #14
0
        /// <summary>
        /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it.
        /// The returned diagnostics are then ordered by location in the source document.
        /// </summary>
        /// <param name="analyzer">The analyzer to run on the documents</param>
        /// <param name="documents">The Documents that the analyzer will be run on</param>
        /// <returns>An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location</returns>
        protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer analyzer, Document[] documents)
        {
            if (documents is null)
            {
                throw new ArgumentNullException(nameof(documents));
            }

            var projects = new HashSet <Project>();

            foreach (Document document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = new List <Diagnostic>();

            foreach (Project project in projects)
            {
                CompilationWithAnalyzers    compilationWithAnalyzers = project.GetCompilationAsync().Result.WithAnalyzers(ImmutableArray.Create(analyzer));
                ImmutableArray <Diagnostic> diags = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result;
                foreach (Diagnostic diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            Document   document = documents[i];
                            SyntaxTree tree     = document.GetSyntaxTreeAsync().Result;
                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            Diagnostic[] results = SortDiagnostics(diagnostics);
            diagnostics.Clear();
            return(results);
        }
コード例 #15
0
        public async Task <List <Diagnostic> > GetDiagnosticsAsync(string sourceCode)
        {
            var compilation = new CompilationWithAnalyzers(
                GetCompilation(sourceCode),
                ImmutableArray.Create <DiagnosticAnalyzer>(new EqualityAnalyzer()),
                new CompilationWithAnalyzersOptions(
                    new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty),
                    (ex, _, _) => Assert.True(false, ex.Message),
                    concurrentAnalysis: false,
                    logAnalyzerExecutionTime: false));
            var diagnostics = await compilation
                              .GetAnalyzerDiagnosticsAsync()
                              .ConfigureAwait(false);

            return(diagnostics
                   .OrderBy(x => x.Id)
                   .ToList());
        }
コード例 #16
0
        private static async Task <ImmutableArray <Diagnostic> > GetDiagnosticsAsync(Project project, DiagnosticAnalyzer analyzer)
        {
            Compilation compilation = await project.GetCompilationAsync().ConfigureAwait(false);

            //foreach (Diagnostic diagnostic in compilation.GetDiagnostics())
            //{
            //    if (diagnostic.Descriptor.DefaultSeverity == DiagnosticSeverity.Error
            //        && diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Compiler))
            //    {
            //        Debug.WriteLine(diagnostic.ToString());
            //    }
            //}

            compilation = EnableDiagnosticsDisabledByDefault(analyzer, compilation);

            CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create(analyzer));

            return(await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false));
        }
コード例 #17
0
        public static async Task ProcessProject(FileInfo projectFile)
        {
            if (projectFile is null)
            {
                throw new ArgumentNullException(nameof(projectFile));
            }

            using var workspace = MSBuildWorkspace.Create();
            Project project = await workspace.OpenProjectAsync(projectFile.FullName).ConfigureAwait(false);

            CompilationWithAnalyzers compilationWithAnalyzers = (await project.GetCompilationAsync().ConfigureAwait(false))
                                                                .WithAnalyzers(ImmutableArray.Create(GetAnalyzers().ToArray()));

            ImmutableArray <Diagnostic> diags = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false);

            foreach (Diagnostic diag in diags)
            {
                Assert.Fail(diag.ToString());
            }
        }
コード例 #18
0
        private async Task <ImmutableArray <Diagnostic> > GetDiagnosticsAsync(Document document)
        {
            var         analyzers   = ImmutableArray.Create(this.CreateAnalyzer());
            Compilation compilation = await document.Project.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false);

            CompilationWithAnalyzers compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, cancellationToken: CancellationToken.None);

            compilation.GetDiagnostics(CancellationToken.None);

            foreach (Diagnostic diagnostic in await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false))
            {
                Location location = diagnostic.Location;
                if (location.IsInSource && location.SourceTree == (SyntaxTree)document.GetSyntaxTreeAsync(CancellationToken.None).Result)
                {
                    ImmutableArray.CreateBuilder <Diagnostic>().Add(diagnostic);
                }
            }

            return(ImmutableArray.CreateBuilder <Diagnostic>().ToImmutable());
        }
コード例 #19
0
        /// <summary>
        /// Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it.
        /// The returned diagnostics are then ordered by location in the source document.
        /// </summary>
        /// <param name="analyzer">The analyzer to run on the documents</param>
        /// <param name="documents">The Documents that the analyzer will be run on</param>
        /// <returns>An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location</returns>
        protected async Task <Diagnostic[]> GetSortedDiagnosticsFromDocuments(DiagnosticAnalyzer analyzer, Document[] documents)
        {
            HashSet <Project> projects = new HashSet <Project>();

            foreach (Document document in documents)
            {
                projects.Add(document.Project);
            }

            List <Diagnostic> diagnostics = new List <Diagnostic>();

            foreach (Project project in projects)
            {
                CompilationWithAnalyzers    compilationWithAnalyzers = (await project.GetCompilationAsync()).WithAnalyzers(ImmutableArray.Create(analyzer));
                ImmutableArray <Diagnostic> diags = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();

                foreach (Diagnostic diag in diags)
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        foreach (Document document in documents)
                        {
                            SyntaxTree tree = await document.GetSyntaxTreeAsync();

                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            Diagnostic[] results = SortDiagnostics(diagnostics);
            diagnostics.Clear();
            return(results);
        }
コード例 #20
0
        public async Task <IEnumerable <ISymbol> > GetSymbolsAsync(
            Project project,
            RenameScope scope,
            CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(
                options: default(AnalyzerOptions),
                onAnalyzerException: default(Action <Exception, DiagnosticAnalyzer, Diagnostic>),
                concurrentAnalysis: true,
                logAnalyzerExecutionTime: false,
                reportSuppressedDiagnostics: false);

            Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            ImmutableArray <SymbolKind> symbolKinds = scope switch
            {
                RenameScope.Type => ImmutableArray.Create(SymbolKind.NamedType),
                RenameScope.Member => ImmutableArray.Create(SymbolKind.Field, SymbolKind.Event, SymbolKind.Method, SymbolKind.Property),
                RenameScope.Local => ImmutableArray.Create(SymbolKind.Field, SymbolKind.Event, SymbolKind.Method, SymbolKind.Property),
                _ => throw new InvalidOperationException(),
            };

            var analyzer = new Analyzer(
                symbolKinds,
                IncludeGeneratedCode);

            var compilationWithAnalyzers = new CompilationWithAnalyzers(
                compilation,
                ImmutableArray.Create((DiagnosticAnalyzer)analyzer),
                compilationWithAnalyzersOptions);

            ImmutableArray <Diagnostic> _ = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

            return(analyzer.Symbols);
        }
コード例 #21
0
ファイル: SpellingFixer.cs プロジェクト: skyhoshi/Roslynator
        public async Task <ImmutableArray <SpellingFixResult> > FixProjectAsync(
            Project project,
            CancellationToken cancellationToken = default)
        {
            project = CurrentSolution.GetProject(project.Id);

            ISpellingService service = MefWorkspaceServices.Default.GetService <ISpellingService>(project.Language);

            if (service == null)
            {
                return(ImmutableArray <SpellingFixResult> .Empty);
            }

            ImmutableArray <Diagnostic> previousDiagnostics         = ImmutableArray <Diagnostic> .Empty;
            ImmutableArray <Diagnostic> previousPreviousDiagnostics = ImmutableArray <Diagnostic> .Empty;

            ImmutableArray <SpellingFixResult> .Builder results = ImmutableArray.CreateBuilder <SpellingFixResult>();

            bool nonSymbolsFixed = (Options.ScopeFilter & (SpellingScopeFilter.NonSymbol)) == 0;

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(
                    options: default(AnalyzerOptions),
                    onAnalyzerException: default(Action <Exception, DiagnosticAnalyzer, Diagnostic>),
                    concurrentAnalysis: true,
                    logAnalyzerExecutionTime: false,
                    reportSuppressedDiagnostics: false);

                Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                DiagnosticAnalyzer analyzer = service.CreateAnalyzer(SpellingData, Options);

                var compilationWithAnalyzers = new CompilationWithAnalyzers(
                    compilation,
                    ImmutableArray.Create(analyzer),
                    compilationWithAnalyzersOptions);

                ImmutableArray <Diagnostic> diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

#if DEBUG
                foreach (IGrouping <Diagnostic, Diagnostic> grouping in diagnostics
                         .GroupBy(f => f, DiagnosticDeepEqualityComparer.Instance))
                {
                    using (IEnumerator <Diagnostic> en = grouping.GetEnumerator())
                    {
                        if (en.MoveNext() &&
                            en.MoveNext())
                        {
                            Debug.Fail(DiagnosticFormatter.FormatDiagnostic(en.Current));
                        }
                    }
                }
#endif
                int length = diagnostics.Length;

                if (length == 0)
                {
                    break;
                }

                if (length == previousDiagnostics.Length &&
                    !diagnostics.Except(previousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any())
                {
                    break;
                }

                if (length == previousPreviousDiagnostics.Length &&
                    !diagnostics.Except(previousPreviousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any())
                {
                    LogHelpers.WriteInfiniteLoopSummary(diagnostics, previousDiagnostics, project, FormatProvider);
                    break;
                }

                var spellingDiagnostics = new List <SpellingDiagnostic>();

                foreach (Diagnostic diagnostic in diagnostics)
                {
                    Debug.Assert(diagnostic.Id == CommonDiagnosticIdentifiers.PossibleMisspellingOrTypo, diagnostic.Id);

                    if (diagnostic.Id != CommonDiagnosticIdentifiers.PossibleMisspellingOrTypo)
                    {
                        if (diagnostic.IsAnalyzerExceptionDiagnostic())
                        {
                            LogHelpers.WriteDiagnostic(diagnostic, baseDirectoryPath: Path.GetDirectoryName(project.FilePath), formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Detailed);
                        }

                        continue;
                    }

                    SpellingDiagnostic spellingDiagnostic = service.CreateSpellingDiagnostic(diagnostic);

                    spellingDiagnostics.Add(spellingDiagnostic);
                }

                if (!nonSymbolsFixed)
                {
                    List <SpellingFixResult> commentResults = await FixCommentsAsync(project, spellingDiagnostics, cancellationToken).ConfigureAwait(false);

                    results.AddRange(commentResults);
                    nonSymbolsFixed = true;
                }

                if ((Options.ScopeFilter & SpellingScopeFilter.Symbol) == 0)
                {
                    break;
                }

                (List <SpellingFixResult> symbolResults, bool allIgnored) = await FixSymbolsAsync(
                    project,
                    spellingDiagnostics,
                    service.SyntaxFacts,
                    cancellationToken)
                                                                            .ConfigureAwait(false);

                results.AddRange(symbolResults);

                if (allIgnored)
                {
                    break;
                }

                if (Options.DryRun)
                {
                    break;
                }

                project = CurrentSolution.GetProject(project.Id);

                previousPreviousDiagnostics = previousDiagnostics;
                previousDiagnostics         = diagnostics;
            }

            return(results.ToImmutableArray());
        }
コード例 #22
0
        private async Task <FixResult> FixProjectAsync(Project project, CancellationToken cancellationToken = default)
        {
            string language = project.Language;

            ImmutableArray <Assembly> assemblies = (Options.IgnoreAnalyzerReferences) ? ImmutableArray <Assembly> .Empty : project.AnalyzerReferences
                                                   .Distinct()
                                                   .OfType <AnalyzerFileReference>()
                                                   .Select(f => f.GetAssembly())
                                                   .Where(f => !_analyzerFiles.Contains(f.FullName))
                                                   .ToImmutableArray();

            ImmutableArray <DiagnosticAnalyzer> analyzers = _analyzerFiles
                                                            .GetAnalyzers(language)
                                                            .AddRange(_analyzerFileCache.GetAnalyzers(assemblies, language));

            if (!analyzers.Any())
            {
                return(FixResult.NoAnalyzers);
            }

            ImmutableArray <CodeFixProvider> fixers = _analyzerFiles
                                                      .GetFixers(language)
                                                      .AddRange(_analyzerFileCache.GetFixers(assemblies, language));

            if (!fixers.Any())
            {
                return(FixResult.NoFixers);
            }

            Dictionary <string, ImmutableArray <DiagnosticAnalyzer> > analyzersById = analyzers
                                                                                      .SelectMany(f => f.SupportedDiagnostics.Select(id => (id.Id, analyzer: f)))
                                                                                      .GroupBy(f => f.Id)
                                                                                      .ToDictionary(f => f.Key, g => g.Select(f => f.analyzer).Distinct().ToImmutableArray());

            Dictionary <string, ImmutableArray <CodeFixProvider> > fixersById = fixers
                                                                                .Where(f => f.GetFixAllProvider() != null)
                                                                                .SelectMany(f => f.FixableDiagnosticIds.Select(id => (id, fixer: f)))
                                                                                .GroupBy((f) => f.id)
                                                                                .ToDictionary(f => f.Key, g => g.Select(f => f.fixer).ToImmutableArray());

            ImmutableArray <Diagnostic> previousDiagnostics = ImmutableArray <Diagnostic> .Empty;

            int iterationCount = 1;

            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                project = CurrentSolution.GetProject(project.Id);

                WriteLine($"  Compile '{project.Name}'{((iterationCount > 1) ? $" iteration {iterationCount}" : "")}");

                Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                if (!VerifyCompilerDiagnostics(compilation, cancellationToken))
                {
                    return(FixResult.CompilerError);
                }

                var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, DefaultCompilationWithAnalyzersOptions);

                WriteLine($"  Analyze '{project.Name}'");

                ImmutableArray <Diagnostic> diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);

                foreach (string message in diagnostics
                         .Where(f => f.Id.StartsWith("AD", StringComparison.Ordinal))
                         .Select(f => f.ToString())
                         .Distinct())
                {
                    WriteLine(message, ConsoleColor.Yellow);
                }

                diagnostics = diagnostics
                              .Where(f => f.Severity != DiagnosticSeverity.Hidden &&
                                     analyzersById.ContainsKey(f.Id) &&
                                     fixersById.ContainsKey(f.Id) &&
                                     !Options.IgnoredDiagnosticIds.Contains(f.Id))
                              .ToImmutableArray();

                int length = diagnostics.Length;

                if (length == 0)
                {
                    break;
                }

                if (length == previousDiagnostics.Length &&
                    !diagnostics.Except(previousDiagnostics, DiagnosticDeepEqualityComparer.Instance).Any())
                {
                    break;
                }

                WriteLine($"  Found {length} {((length == 1) ? "diagnostic" : "diagnostics")} in '{project.Name}'");

                foreach (string diagnosticId in diagnostics
                         .Select(f => f.Id)
                         .Distinct()
                         .OrderBy(f => f))
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    FixResult result = await FixDiagnosticsAsync(
                        diagnosticId,
                        CurrentSolution.GetProject(project.Id),
                        analyzersById[diagnosticId],
                        fixersById[diagnosticId],
                        cancellationToken).ConfigureAwait(false);

                    if (result == FixResult.CompilerError)
                    {
                        return(result);
                    }
                }

                previousDiagnostics = diagnostics;
                iterationCount++;
            }

            return(FixResult.Success);
        }
コード例 #23
0
ファイル: CodeAnalyzer.cs プロジェクト: skyhoshi/Roslynator
        private async Task <ProjectAnalysisResult> AnalyzeProjectCoreAsync(Project project, ImmutableArray <DiagnosticAnalyzer> analyzers, CancellationToken cancellationToken = default)
        {
            LogHelpers.WriteUsedAnalyzers(analyzers, null, Options, ConsoleColors.DarkGray, Verbosity.Diagnostic);

            cancellationToken.ThrowIfCancellationRequested();

            Compilation compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            ImmutableArray <Diagnostic> compilerDiagnostics = (Options.IgnoreCompilerDiagnostics)
                ? ImmutableArray <Diagnostic> .Empty
                : compilation.GetDiagnostics(cancellationToken);

            compilerDiagnostics = FilterDiagnostics(compilerDiagnostics, project, cancellationToken).ToImmutableArray();

            ImmutableArray <Diagnostic> diagnostics = ImmutableArray <Diagnostic> .Empty;

            ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> telemetry = ImmutableDictionary <DiagnosticAnalyzer, AnalyzerTelemetryInfo> .Empty;

            if (analyzers.Any())
            {
                var compilationWithAnalyzersOptions = new CompilationWithAnalyzersOptions(
                    options: project.AnalyzerOptions,
                    onAnalyzerException: default(Action <Exception, DiagnosticAnalyzer, Diagnostic>),
                    concurrentAnalysis: Options.ConcurrentAnalysis,
                    logAnalyzerExecutionTime: Options.LogAnalyzerExecutionTime,
                    reportSuppressedDiagnostics: Options.ReportSuppressedDiagnostics);

                var compilationWithAnalyzers = new CompilationWithAnalyzers(compilation, analyzers, compilationWithAnalyzersOptions);

                if (Options.LogAnalyzerExecutionTime)
                {
                    AnalysisResult analysisResult = await compilationWithAnalyzers.GetAnalysisResultAsync(cancellationToken).ConfigureAwait(false);

                    diagnostics = analysisResult.GetAllDiagnostics();
                    telemetry   = analysisResult.AnalyzerTelemetryInfo;
                }
                else
                {
                    diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync(cancellationToken).ConfigureAwait(false);
                }
            }

            string projectDirectoryPath = Path.GetDirectoryName(project.FilePath);

            LogHelpers.WriteDiagnostics(FilterDiagnostics(diagnostics.Where(f => f.IsAnalyzerExceptionDiagnostic()), project, cancellationToken).ToImmutableArray(), baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Detailed);
#if DEBUG
            if (ConsoleOut.Verbosity >= Verbosity.Detailed &&
                diagnostics.Any(f => f.IsAnalyzerExceptionDiagnostic()))
            {
                Console.Write("Stop (Y/N)? ");

                if (char.ToUpperInvariant((char)Console.Read()) == 'Y')
                {
                    throw new OperationCanceledException();
                }
            }
#endif
            diagnostics = FilterDiagnostics(diagnostics.Where(f => !f.IsAnalyzerExceptionDiagnostic()), project, cancellationToken).ToImmutableArray();

            LogHelpers.WriteDiagnostics(compilerDiagnostics, baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Normal);

            LogHelpers.WriteDiagnostics(diagnostics, baseDirectoryPath: projectDirectoryPath, formatProvider: FormatProvider, indentation: "  ", verbosity: Verbosity.Normal);

            return(ProjectAnalysisResult.Create(project, compilerDiagnostics, diagnostics, telemetry));
        }
コード例 #24
0
        static void Main(string[] args)
        {
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
                using System;

                namespace RoslynCompileSample
                {
                    public class Writer
                    {
                        public void Write(string message)
                        {
                            var prefix = GetMessagePrefix();
                            Console.WriteLine(prefix + ""-"" + message);
                        }

                        public string GetMessagePrefix()
                        {
                            return ""pre"";
                        }
                    }
                }");

            string assemblyName = Path.GetRandomFileName();

            MetadataReference[] references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
            };

            string analyzerAssemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..\lib\DotNetDoodle.Analyzers.dll");
            ImmutableArray <DiagnosticAnalyzer> diagnosticAnalyzers = new AnalyzerFileReference(analyzerAssemblyPath).GetAnalyzers(LanguageNames.CSharp);

            CompilationWithAnalyzers compilationWithAnalyzers = CSharpCompilation.Create(
                assemblyName,
                syntaxTrees: new[] { syntaxTree },
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)).WithAnalyzers(diagnosticAnalyzers);

            ImmutableArray <Diagnostic> diagsnostics = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result;

            using (var ms = new MemoryStream())
            {
                EmitResult result = compilationWithAnalyzers.Compilation.Emit(ms);
                ImmutableArray <Diagnostic> allDiagsnostics = result.Diagnostics.Concat(diagsnostics).ToImmutableArray();

                if (!result.Success)
                {
                    IEnumerable <Diagnostic> failures = allDiagsnostics.Where(diagnostic =>
                                                                              diagnostic.IsWarningAsError ||
                                                                              diagnostic.Severity == DiagnosticSeverity.Error);

                    foreach (Diagnostic diagnostic in failures)
                    {
                        Console.Error.WriteLine("ERROR: {0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                    }

                    WriteWarnings(allDiagsnostics);
                }
                else
                {
                    WriteWarnings(allDiagsnostics);

                    ms.Seek(0, SeekOrigin.Begin);
                    Assembly assembly = Assembly.Load(ms.ToArray());

                    Type   type = assembly.GetType("RoslynCompileSample.Writer");
                    object obj  = Activator.CreateInstance(type);
                    type.InvokeMember("Write",
                                      BindingFlags.Default | BindingFlags.InvokeMethod,
                                      null,
                                      obj,
                                      new object[] { "Hello World" });
                }
            }

            Console.ReadLine();
        }
コード例 #25
0
    /// <summary>
    ///     Given an analyzer and a document to apply it to, run the analyzer and gather an array of diagnostics found in it.
    ///     The returned diagnostics are then ordered by location in the source document.
    /// </summary>
    /// <param name="analyzer">The analyzer to run on the documents</param>
    /// <param name="documents">The Documents that the analyzer will be run on</param>
    /// <returns>An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location</returns>
    protected static async Task <IReadOnlyList <Diagnostic> > GetSortedDiagnosticsFromDocumentsAsync(DiagnosticAnalyzer analyzer, Document[] documents)
    {
        HashSet <Project> projects = new();

        foreach (Document document in documents)
        {
            projects.Add(document.Project);
        }

        List <Diagnostic> diagnostics = new();

        foreach (Project project in projects)
        {
            Compilation?compilation = await project.GetCompilationAsync();

            if (compilation == null)
            {
                continue;
            }

            ImmutableArray <Diagnostic> compilerErrors = compilation.GetDiagnostics();

            if (compilerErrors.Length != 0)
            {
                StringBuilder errors = compilerErrors.Where(IsReportableCSharpError)
                                       .Aggregate(new StringBuilder(), func: (current, compilerError) => current.Append(compilerError));

                if (errors.Length != 0)
                {
                    throw new UnitTestSourceException("Please correct following compiler errors in your unit test source:" + errors);
                }
            }

            CompilationWithAnalyzers    compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create(analyzer));
            ImmutableArray <Diagnostic> diags = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync();

            foreach (Diagnostic diag in diags)
            {
                if (diag.Location == Location.None || diag.Location.IsInMetadata)
                {
                    diagnostics.Add(diag);
                }
                else
                {
                    foreach (Document document in documents)
                    {
                        SyntaxTree?tree = await document.GetSyntaxTreeAsync();

                        if (tree != null && tree == diag.Location.SourceTree)
                        {
                            diagnostics.Add(diag);
                        }
                    }
                }
            }
        }

        IReadOnlyList <Diagnostic> results = SortDiagnostics(diagnostics);

        diagnostics.Clear();

        return(results);
    }