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); }
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)); }
public static bool SupportsSemanticDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver) { bool discarded; return(analyzer.SupportsSemanticDiagnosticAnalysis(driver, out discarded)); }
public static bool SupportsProjectDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver) { var category = analyzer.GetDiagnosticAnalyzerCategory(driver); return((category & DiagnosticAnalyzerCategory.ProjectAnalysis) != 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); }
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); }
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); }