提交 ca03cd74 编写于 作者: M Manish Vasani

Fix DiagnosticAnalyzerExtensions.GetDiagnosticAnalyzerCategory to return...

Fix DiagnosticAnalyzerExtensions.GetDiagnosticAnalyzerCategory to return DiagnosticAnalyzerCategory.SemanticDocumentAnalysis if the analyzer has semantic actions and cannot support semantic span based analysis.

Fixes #1709
上级 e8b34974
......@@ -1033,5 +1033,22 @@ class C
Diagnostic(CodeBlockActionAnalyzer.CodeBlockPerCompilationRule.Id, "M").WithArguments("M").WithLocation(4, 17)
});
}
[Fact, WorkItem(1709, "https://github.com/dotnet/roslyn/issues/1709")]
public void TestCodeBlockAction_OnlyStatelessAction()
{
string source = @"
class C
{
public void M() {}
}";
var analyzers = new DiagnosticAnalyzer[] { new CodeBlockActionAnalyzer(onlyStatelessAction: true) };
// Verify, code block action diagnostics.
CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics()
.VerifyAnalyzerDiagnostics(analyzers, null, null, logAnalyzerExceptionAsDiagnostics: false,
expected: Diagnostic(CodeBlockActionAnalyzer.CodeBlockTopLevelRule.Id, "M").WithArguments("M").WithLocation(4, 17));
}
}
}
......@@ -799,5 +799,26 @@ End Class
AnalyzerDiagnostic(CodeBlockActionAnalyzer.CodeBlockTopLevelRule.Id, <![CDATA[M]]>).WithArguments("M"),
AnalyzerDiagnostic(CodeBlockActionAnalyzer.CodeBlockPerCompilationRule.Id, <![CDATA[M]]>).WithArguments("M"))
End Sub
<Fact, WorkItem(1709, "https://github.com/dotnet/roslyn/issues/1709")>
Public Sub TestCodeBlockAction_OnlyStatelessAction()
Dim analyzer = New CodeBlockActionAnalyzer(onlyStatelessAction:=True)
Dim sources = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Public Sub M()
End Sub
End Class
]]>
</file>
</compilation>
Dim compilation = CreateCompilationWithMscorlibAndReferences(sources, references:={SystemCoreRef, MsvbRef})
compilation.VerifyDiagnostics()
compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, False,
AnalyzerDiagnostic(CodeBlockActionAnalyzer.CodeBlockTopLevelRule.Id, <![CDATA[M]]>).WithArguments("M"))
End Sub
End Class
End Namespace
......@@ -1447,12 +1447,41 @@ End Class
TestCodeBlockActionCore(test)
End Sub
Private Sub TestCodeBlockActionCore(test As XElement)
<Fact, WorkItem(1709, "https://github.com/dotnet/roslyn/issues/1709")>
Public Sub TestCodeBlockAction_OnlyStatelessAction()
Dim test = <Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class C
{
public void M() {}
}
</Document>
</Project>
</Workspace>
TestCodeBlockActionCore(test, onlyStatelessAction:=True)
test = <Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Class C
Public Sub M()
End Sub
End Class
</Document>
</Project>
</Workspace>
TestCodeBlockActionCore(test, onlyStatelessAction:=True)
End Sub
Private Sub TestCodeBlockActionCore(test As XElement, Optional onlyStatelessAction As Boolean = False)
Using workspace = TestWorkspaceFactory.CreateWorkspace(test)
Dim project = workspace.CurrentSolution.Projects.Single()
' Add analyzer
Dim analyzer = New CodeBlockActionAnalyzer()
Dim analyzer = New CodeBlockActionAnalyzer(onlyStatelessAction)
Dim analyzerReference = New AnalyzerImageReference(ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer))
project = project.AddAnalyzerReference(analyzerReference)
......@@ -1467,13 +1496,17 @@ End Class
Dim diagnostics = diagnosticService.GetDiagnosticsForSpanAsync(document,
document.GetSyntaxRootAsync().WaitAndGetResult(CancellationToken.None).FullSpan,
CancellationToken.None).WaitAndGetResult(CancellationToken.None)
Assert.Equal(2, diagnostics.Count())
Dim expectedCount = If(onlyStatelessAction, 1, 2)
Assert.Equal(expectedCount, diagnostics.Count())
Dim diagnostic = diagnostics.Single(Function(d) d.Id = CodeBlockActionAnalyzer.CodeBlockTopLevelRule.Id)
Assert.Equal("CodeBlock : M", diagnostic.Message)
diagnostic = diagnostics.Single(Function(d) d.Id = CodeBlockActionAnalyzer.CodeBlockPerCompilationRule.Id)
Assert.Equal("CodeBlock : M", diagnostic.Message)
Dim stateFullDiagnostics = diagnostics.Where(Function(d) d.Id = CodeBlockActionAnalyzer.CodeBlockPerCompilationRule.Id)
Assert.Equal(expectedCount - 1, stateFullDiagnostics.Count)
If Not onlyStatelessAction Then
Assert.Equal("CodeBlock : M", stateFullDiagnostics.Single().Message)
End If
End Using
End Sub
End Class
......
......@@ -45,24 +45,21 @@ public static DiagnosticAnalyzerCategory GetDiagnosticAnalyzerCategory(this Diag
{
// 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;
category |= (DiagnosticAnalyzerCategory.SyntaxAnalysis | DiagnosticAnalyzerCategory.SemanticDocumentAnalysis | DiagnosticAnalyzerCategory.ProjectAnalysis);
cantSupportSemanticSpanAnalysis = true;
}
if (analyzerActions.CompilationEndActionsCount > 0 || analyzerActions.CompilationActionsCount > 0 || analyzerActions.CompilationStartActionsCount > 0)
if (analyzerActions.CompilationActionsCount > 0 || analyzerActions.CompilationStartActionsCount > 0)
{
category |= DiagnosticAnalyzerCategory.ProjectAnalysis;
}
if (!cantSupportSemanticSpanAnalysis)
if (HasSemanticDocumentActions(analyzerActions))
{
if (analyzerActions.SymbolActionsCount > 0 ||
analyzerActions.CodeBlockStartActionsCount > 0 ||
analyzerActions.CodeBlockEndActionsCount > 0 ||
analyzerActions.SyntaxNodeActionsCount > 0)
{
category |= DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
}
var semanticDocumentAnalysisCategory = cantSupportSemanticSpanAnalysis ?
DiagnosticAnalyzerCategory.SemanticDocumentAnalysis :
DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
category |= semanticDocumentAnalysisCategory;
}
}
}
......@@ -70,6 +67,15 @@ public static DiagnosticAnalyzerCategory GetDiagnosticAnalyzerCategory(this Diag
return category;
}
private static bool HasSemanticDocumentActions(AnalyzerActions analyzerActions)
{
return analyzerActions.SymbolActionsCount > 0 ||
analyzerActions.SyntaxNodeActionsCount > 0 ||
analyzerActions.SemanticModelActionsCount > 0 ||
analyzerActions.CodeBlockActionsCount > 0 ||
analyzerActions.CodeBlockStartActionsCount > 0;
}
public static bool SupportsSyntaxDiagnosticAnalysis(this DiagnosticAnalyzer analyzer, DiagnosticAnalyzerDriver driver)
{
var category = analyzer.GetDiagnosticAnalyzerCategory(driver);
......
......@@ -190,6 +190,13 @@ public override void Initialize(AnalysisContext context)
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public class CodeBlockActionAnalyzer : DiagnosticAnalyzer
{
private readonly bool _onlyStatelessAction;
public CodeBlockActionAnalyzer(bool onlyStatelessAction = false)
{
_onlyStatelessAction = onlyStatelessAction;
}
public static readonly DiagnosticDescriptor CodeBlockTopLevelRule = new DiagnosticDescriptor(
"CodeBlockTopLevelRuleId",
"CodeBlockTopLevelRuleTitle",
......@@ -221,13 +228,16 @@ public override void Initialize(AnalysisContext context)
codeBlockContext.ReportDiagnostic(Diagnostic.Create(CodeBlockTopLevelRule, codeBlockContext.OwningSymbol.Locations[0], codeBlockContext.OwningSymbol.Name));
});
context.RegisterCompilationStartAction(compilationStartContext =>
if (!_onlyStatelessAction)
{
compilationStartContext.RegisterCodeBlockAction(codeBlockContext =>
context.RegisterCompilationStartAction(compilationStartContext =>
{
codeBlockContext.ReportDiagnostic(Diagnostic.Create(CodeBlockPerCompilationRule, codeBlockContext.OwningSymbol.Locations[0], codeBlockContext.OwningSymbol.Name));
compilationStartContext.RegisterCodeBlockAction(codeBlockContext =>
{
codeBlockContext.ReportDiagnostic(Diagnostic.Create(CodeBlockPerCompilationRule, codeBlockContext.OwningSymbol.Locations[0], codeBlockContext.OwningSymbol.Name));
});
});
});
}
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册