public static bool SupportsSemanticDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver, out bool supportsSemanticSpanAnalysis)
 {
     var category = analyzer.GetDiagnosticAnalyzerCategory(driver);
     supportsSemanticSpanAnalysis = (category & DiagnosticAnalyzerCategory.SemanticSpanAnalysis) != 0;
     return supportsSemanticSpanAnalysis ||
         (category & DiagnosticAnalyzerCategory.SemanticDocumentAnalysis) != 0;
 }
        public static DiagnosticAnalyzerCategory GetDiagnosticAnalyzerCategory(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
        {
            var category = DiagnosticAnalyzerCategory.None;

            if (analyzer is DocumentDiagnosticAnalyzer)
            {
                category |= DiagnosticAnalyzerCategory.SyntaxAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
            }
            else if (analyzer is ProjectDiagnosticAnalyzer)
            {
                category |= DiagnosticAnalyzerCategory.ProjectAnalysis;
            }
            else if (driver != null)
            {
                // If an analyzer requires or might require the entire document, then it cannot promise
                // to be able to operate on a limited span of the document. In practical terms, no analyzer
                // can have both SemanticDocumentAnalysis and SemanticSpanAnalysis as categories.
                bool cantSupportSemanticSpanAnalysis = false;
                var analyzerActions = driver.GetSessionAnalyzerActions(analyzer);
                if (analyzerActions != null)
                {
                    if (analyzerActions.SyntaxTreeActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.SyntaxAnalysis;
                    }

                    if (analyzerActions.SemanticModelActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
                        cantSupportSemanticSpanAnalysis = true;
                    }

                    if (analyzerActions.CompilationStartActionsCount > 0)
                    {
                        // It is not possible to know what actions a compilation start action will register without executing it,
                        // so return a worst-case categorization.
                        category |= DiagnosticAnalyzerCategory.SyntaxAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis | DiagnosticAnalyzerCategory.ProjectAnalysis;
                        cantSupportSemanticSpanAnalysis = true;
                    }

                    if (analyzerActions.CompilationEndActionsCount > 0 || analyzerActions.CompilationStartActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.ProjectAnalysis;
                    }

                    if (!cantSupportSemanticSpanAnalysis)
                    {
                        if (analyzerActions.SymbolActionsCount > 0 ||
                            analyzerActions.CodeBlockStartActionsCount > 0 ||
                            analyzerActions.CodeBlockEndActionsCount > 0 ||
                            analyzerActions.SyntaxNodeActionsCount > 0)
                        {
                            category |= DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
                        }
                    }
                }
            }

            return category;
        }
 public static bool SupportsProjectDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
 {
     var category = analyzer.GetDiagnosticAnalyzerCategory(driver);
     return (category & DiagnosticAnalyzerCategory.ProjectAnalysis) != 0;
 }
 public static bool SupportsSemanticDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
 {
     bool discarded;
     return analyzer.SupportsSemanticDiagnosticAnalysis(driver, out discarded);
 }
Beispiel #5
0
        private static IEnumerable <Diagnostic> GetDiagnostics(DiagnosticAnalyzer analyzerOpt, Document document, TextSpan span, Project project, bool getDocumentDiagnostics, bool getProjectDiagnostics, Action <Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException, bool logAnalyzerExceptionAsDiagnostics)
        {
            var documentDiagnostics = SpecializedCollections.EmptyEnumerable <Diagnostic>();
            var projectDiagnostics  = SpecializedCollections.EmptyEnumerable <Diagnostic>();

            // If no user diagnostic analyzer, then test compiler diagnostics.
            var analyzer = analyzerOpt ?? DiagnosticExtensions.GetCompilerDiagnosticAnalyzer(project.Language);

            // If the test is not configured with a custom onAnalyzerException handler AND has not requested exceptions to be handled and logged as diagnostics, then FailFast on exceptions.
            if (onAnalyzerException == null && !logAnalyzerExceptionAsDiagnostics)
            {
                onAnalyzerException = DiagnosticExtensions.FailFastOnAnalyzerException;
            }

            var exceptionDiagnosticsSource = new TestHostDiagnosticUpdateSource(project.Solution.Workspace);

            if (getDocumentDiagnostics)
            {
                var tree          = document.GetSyntaxTreeAsync().Result;
                var root          = document.GetSyntaxRootAsync().Result;
                var semanticModel = document.GetSemanticModelAsync().Result;

                var builder = new List <Diagnostic>();
                var nodeInBodyAnalyzerService = document.Project.Language == LanguageNames.CSharp ?
                                                (ISyntaxNodeAnalyzerService) new CSharpSyntaxNodeAnalyzerService() :
                                                new VisualBasicSyntaxNodeAnalyzerService();

                // Lets replicate the IDE diagnostic incremental analyzer behavior to determine span to test:
                //  (a) If the span is contained within a method level member and analyzer supports semantic in span: analyze in member span.
                //  (b) Otherwise, analyze entire syntax tree span.
                var spanToTest = root.FullSpan;

                var driver = new DiagnosticAnalyzerDriver(document, spanToTest, root,
                                                          syntaxNodeAnalyzerService: nodeInBodyAnalyzerService,
                                                          hostDiagnosticUpdateSource: exceptionDiagnosticsSource,
                                                          overriddenOnAnalyzerException: onAnalyzerException);
                var  diagnosticAnalyzerCategory = analyzer.GetDiagnosticAnalyzerCategory(driver);
                bool supportsSemanticInSpan     = (diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SemanticSpanAnalysis) != 0;
                if (supportsSemanticInSpan)
                {
                    var syntaxFacts = document.Project.LanguageServices.GetService <ISyntaxFactsService>();
                    if (syntaxFacts != null)
                    {
                        var member = syntaxFacts.GetContainingMemberDeclaration(root, span.Start);
                        if (member != null && syntaxFacts.IsMethodLevelMember(member) && member.FullSpan.Contains(span))
                        {
                            spanToTest = member.FullSpan;
                        }
                    }
                }

                if ((diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SyntaxAnalysis) != 0)
                {
                    builder.AddRange(driver.GetSyntaxDiagnosticsAsync(analyzer).Result);
                }

                if (supportsSemanticInSpan || (diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SemanticDocumentAnalysis) != 0)
                {
                    builder.AddRange(driver.GetSemanticDiagnosticsAsync(analyzer).Result);
                }

                documentDiagnostics = builder.Where(d => d.Location == Location.None ||
                                                    (d.Location.SourceTree == tree && d.Location.SourceSpan.IntersectsWith(span)));
            }

            if (getProjectDiagnostics)
            {
                var nodeInBodyAnalyzerService = project.Language == LanguageNames.CSharp ?
                                                (ISyntaxNodeAnalyzerService) new CSharpSyntaxNodeAnalyzerService() :
                                                new VisualBasicSyntaxNodeAnalyzerService();
                var driver = new DiagnosticAnalyzerDriver(project, nodeInBodyAnalyzerService, exceptionDiagnosticsSource, overriddenOnAnalyzerException: onAnalyzerException);

                if (analyzer.SupportsProjectDiagnosticAnalysis(driver))
                {
                    projectDiagnostics = driver.GetProjectDiagnosticsAsync(analyzer, null).Result;
                }
            }

            var exceptionDiagnostics = exceptionDiagnosticsSource.TestOnly_GetReportedDiagnostics(analyzer).Select(d => d.ToDiagnostic(tree: null));

            return(documentDiagnostics.Concat(projectDiagnostics).Concat(exceptionDiagnostics));
        }
Beispiel #6
0
        public static bool SupportsSemanticDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
        {
            bool discarded;

            return(analyzer.SupportsSemanticDiagnosticAnalysis(driver, out discarded));
        }
Beispiel #7
0
        public static bool SupportsProjectDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
        {
            var category = analyzer.GetDiagnosticAnalyzerCategory(driver);

            return((category & DiagnosticAnalyzerCategory.ProjectAnalysis) != 0);
        }
Beispiel #8
0
        public static DiagnosticAnalyzerCategory GetDiagnosticAnalyzerCategory(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
        {
            var category = DiagnosticAnalyzerCategory.None;

            if (analyzer is DocumentDiagnosticAnalyzer)
            {
                category |= DiagnosticAnalyzerCategory.SyntaxAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
            }
            else if (analyzer is ProjectDiagnosticAnalyzer)
            {
                category |= DiagnosticAnalyzerCategory.ProjectAnalysis;
            }
            else if (driver != null)
            {
                // If an analyzer requires or might require the entire document, then it cannot promise
                // to be able to operate on a limited span of the document. In practical terms, no analyzer
                // can have both SemanticDocumentAnalysis and SemanticSpanAnalysis as categories.
                bool cantSupportSemanticSpanAnalysis = false;
                var  analyzerActions = driver.GetAnalyzerActionsAsync(analyzer).WaitAndGetResult(driver.CancellationToken);
                if (analyzerActions != null)
                {
                    if (analyzerActions.SyntaxTreeActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.SyntaxAnalysis;
                    }

                    if (analyzerActions.SemanticModelActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
                        cantSupportSemanticSpanAnalysis = true;
                    }

                    if (analyzerActions.CompilationStartActionsCount > 0)
                    {
                        // It is not possible to know what actions a compilation start action will register without executing it,
                        // so return a worst-case categorization.
                        category |= DiagnosticAnalyzerCategory.SyntaxAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis | DiagnosticAnalyzerCategory.ProjectAnalysis;
                        cantSupportSemanticSpanAnalysis = true;
                    }

                    if (analyzerActions.CompilationEndActionsCount > 0 || analyzerActions.CompilationActionsCount > 0 || analyzerActions.CompilationStartActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.ProjectAnalysis;
                    }

                    if (!cantSupportSemanticSpanAnalysis)
                    {
                        if (analyzerActions.SymbolActionsCount > 0 ||
                            analyzerActions.CodeBlockStartActionsCount > 0 ||
                            analyzerActions.CodeBlockEndActionsCount > 0 ||
                            analyzerActions.SyntaxNodeActionsCount > 0)
                        {
                            category |= DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
                        }
                    }
                }
            }

            return(category);
        }
Beispiel #9
0
        public static bool SupportsSemanticDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver, out bool supportsSemanticSpanAnalysis)
        {
            var category = analyzer.GetDiagnosticAnalyzerCategory(driver);

            supportsSemanticSpanAnalysis = (category & DiagnosticAnalyzerCategory.SemanticSpanAnalysis) != 0;
            return(supportsSemanticSpanAnalysis ||
                   (category & DiagnosticAnalyzerCategory.SemanticDocumentAnalysis) != 0);
        }
Beispiel #10
0
        private static IEnumerable <Diagnostic> GetDiagnostics(DiagnosticAnalyzer analyzerOpt, Document document, TextSpan span, Project project, bool getDocumentDiagnostics, bool getProjectDiagnostics, bool donotCatchAnalyzerExceptions)
        {
            var documentDiagnostics = SpecializedCollections.EmptyEnumerable <Diagnostic>();
            var projectDiagnostics  = SpecializedCollections.EmptyEnumerable <Diagnostic>();

            // If no user diagnostic analyzer, then test compiler diagnostics.
            var analyzer = analyzerOpt ?? DiagnosticExtensions.GetCompilerDiagnosticAnalyzer(project.Language);

            if (getDocumentDiagnostics)
            {
                var tree          = document.GetSyntaxTreeAsync().Result;
                var root          = document.GetSyntaxRootAsync().Result;
                var semanticModel = document.GetSemanticModelAsync().Result;

                var builder = new List <Diagnostic>();
                var nodeInBodyAnalyzerService = document.Project.Language == LanguageNames.CSharp ?
                                                (ISyntaxNodeAnalyzerService) new CSharpSyntaxNodeAnalyzerService() :
                                                new VisualBasicSyntaxNodeAnalyzerService();

                // Lets replicate the IDE diagnostic incremental analyzer behavior to determine span to test:
                //  (a) If the span is contained within a method level member and analyzer supports semantic in span: analyze in member span.
                //  (b) Otherwise, analyze entire syntax tree span.
                var spanToTest = root.FullSpan;

                var  driver = new DiagnosticAnalyzerDriver(document, spanToTest, root, syntaxNodeAnalyzerService: nodeInBodyAnalyzerService, cancellationToken: CancellationToken.None, testOnly_DonotCatchAnalyzerExceptions: donotCatchAnalyzerExceptions);
                var  diagnosticAnalyzerCategory = analyzer.GetDiagnosticAnalyzerCategory(driver);
                bool supportsSemanticInSpan     = (diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SemanticSpanAnalysis) != 0;
                if (supportsSemanticInSpan)
                {
                    var syntaxFacts = document.Project.LanguageServices.GetService <ISyntaxFactsService>();
                    if (syntaxFacts != null)
                    {
                        var member = syntaxFacts.GetContainingMemberDeclaration(root, span.Start);
                        if (member != null && syntaxFacts.IsMethodLevelMember(member) && member.FullSpan.Contains(span))
                        {
                            spanToTest = member.FullSpan;
                        }
                    }
                }

                if ((diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SyntaxAnalysis) != 0)
                {
                    builder.AddRange(driver.GetSyntaxDiagnosticsAsync(analyzer).Result ?? SpecializedCollections.EmptyEnumerable <Diagnostic>());
                }

                if (supportsSemanticInSpan || (diagnosticAnalyzerCategory & DiagnosticAnalyzerCategory.SemanticDocumentAnalysis) != 0)
                {
                    builder.AddRange(driver.GetSemanticDiagnosticsAsync(analyzer).Result ?? SpecializedCollections.EmptyEnumerable <Diagnostic>());
                }

                documentDiagnostics = builder.Where(d => d.Location == Location.None ||
                                                    (d.Location.SourceTree == tree && d.Location.SourceSpan.IntersectsWith(span)));
            }

            if (getProjectDiagnostics)
            {
                var nodeInBodyAnalyzerService = project.Language == LanguageNames.CSharp ?
                                                (ISyntaxNodeAnalyzerService) new CSharpSyntaxNodeAnalyzerService() :
                                                new VisualBasicSyntaxNodeAnalyzerService();
                var driver = new DiagnosticAnalyzerDriver(project, nodeInBodyAnalyzerService, CancellationToken.None);

                if (analyzer.SupportsProjectDiagnosticAnalysis(driver))
                {
                    projectDiagnostics = driver.GetProjectDiagnosticsAsync(analyzer, null).Result ?? SpecializedCollections.EmptyEnumerable <Diagnostic>();
                }
            }

            return(documentDiagnostics.Concat(projectDiagnostics));
        }
 public static async Task<bool> SupportsProjectDiagnosticAnalysisAsync(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
 {
     var category = await analyzer.GetDiagnosticAnalyzerCategoryAsync(driver).ConfigureAwait(false);
     return (category & DiagnosticAnalyzerCategory.ProjectAnalysis) != 0;
 }
 public static async Task<bool> SupportsSemanticDiagnosticAnalysisAsync(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
 {
     var category = await analyzer.GetDiagnosticAnalyzerCategoryAsync(driver).ConfigureAwait(false);
     return (category & (DiagnosticAnalyzerCategory.SemanticSpanAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis)) != 0;
 }
        public static async Task <bool> SupportsSpanBasedSemanticDiagnosticAnalysisAsync(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
        {
            var category = await analyzer.GetDiagnosticAnalyzerCategoryAsync(driver).ConfigureAwait(false);

            return((category & DiagnosticAnalyzerCategory.SemanticSpanAnalysis) != 0);
        }
        public static async Task <DiagnosticAnalyzerCategory> GetDiagnosticAnalyzerCategoryAsync(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
        {
            var category = DiagnosticAnalyzerCategory.None;

            if (analyzer is DocumentDiagnosticAnalyzer)
            {
                category |= DiagnosticAnalyzerCategory.SyntaxAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
            }
            else if (analyzer is ProjectDiagnosticAnalyzer)
            {
                category |= DiagnosticAnalyzerCategory.ProjectAnalysis;
            }
            else if (driver != null)
            {
                // If an analyzer requires or might require the entire document, then it cannot promise
                // to be able to operate on a limited span of the document. In practical terms, no analyzer
                // can have both SemanticDocumentAnalysis and SemanticSpanAnalysis as categories.
                bool cantSupportSemanticSpanAnalysis = false;
                var  analyzerActions = await driver.GetAnalyzerActionsAsync(analyzer).ConfigureAwait(false);

                if (analyzerActions != null)
                {
                    if (analyzerActions.SyntaxTreeActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.SyntaxAnalysis;
                    }

                    if (analyzerActions.SemanticModelActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
                        cantSupportSemanticSpanAnalysis = true;
                    }

                    if (analyzerActions.CompilationStartActionsCount > 0)
                    {
                        // It is not possible to know what actions a compilation start action will register without executing it,
                        // so return a worst-case categorization.
                        category |= (DiagnosticAnalyzerCategory.SyntaxAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis | DiagnosticAnalyzerCategory.ProjectAnalysis);
                        cantSupportSemanticSpanAnalysis = true;
                    }

                    if (analyzerActions.CompilationActionsCount > 0 || analyzerActions.CompilationStartActionsCount > 0)
                    {
                        category |= DiagnosticAnalyzerCategory.ProjectAnalysis;
                    }

                    if (HasSemanticDocumentActions(analyzerActions))
                    {
                        var semanticDocumentAnalysisCategory = cantSupportSemanticSpanAnalysis ?
                                                               DiagnosticAnalyzerCategory.SemanticDocumentAnalysis :
                                                               DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
                        category |= semanticDocumentAnalysisCategory;
                    }
                }
            }

            return(category);
        }