/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.vb
1 718 строк
87 KB
Jason Malinowski
Switch code that was using Assert.True/False as a replacement for .Fail
21 апр 2026, 23:28
21 апр 2026, 23:28
3bf59ba
Код
Авторство
О чём код?
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Collections.Concurrent Imports System.Collections.Immutable Imports System.Threading Imports Microsoft.CodeAnalysis.CommonDiagnosticAnalyzers Imports Microsoft.CodeAnalysis.Diagnostics Imports Microsoft.CodeAnalysis.Diagnostics.VisualBasic Imports Microsoft.CodeAnalysis.FlowAnalysis Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Roslyn.Test.Utilities Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics Partial Public Class DiagnosticAnalyzerTests Inherits BasicTestBase Public Class ComplainAboutX Inherits DiagnosticAnalyzer Private Shared ReadOnly s_CA9999_UseOfVariableThatStartsWithX As DiagnosticDescriptor = New DiagnosticDescriptor(id:="CA9999_UseOfVariableThatStartsWithX", title:="CA9999_UseOfVariableThatStartsWithX", messageFormat:="Use of variable whose name starts with 'x': '{0}'", category:="Test", defaultSeverity:=DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public Overrides ReadOnly Property SupportedDiagnostics() As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(s_CA9999_UseOfVariableThatStartsWithX) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterSyntaxNodeAction(AddressOf AnalyzeNode, SyntaxKind.IdentifierName) End Sub Public Sub AnalyzeNode(context As SyntaxNodeAnalysisContext) Dim id = CType(context.Node, IdentifierNameSyntax) If id.Identifier.ValueText.StartsWith("x", StringComparison.Ordinal) Then context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(s_CA9999_UseOfVariableThatStartsWithX, id.GetLocation, id.Identifier.ValueText)) End If End Sub End Class <Fact> Public Sub TestGetEffectiveDiagnostics() Dim noneDiagDescriptor = New DiagnosticDescriptor("XX0001", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Hidden, isEnabledByDefault:=True) Dim infoDiagDescriptor = New DiagnosticDescriptor("XX0002", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Info, isEnabledByDefault:=True) Dim warningDiagDescriptor = New DiagnosticDescriptor("XX0003", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Dim errorDiagDescriptor = New DiagnosticDescriptor("XX0004", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Error, isEnabledByDefault:=True) Dim noneDiag = Microsoft.CodeAnalysis.Diagnostic.Create(noneDiagDescriptor, Location.None) Dim infoDiag = Microsoft.CodeAnalysis.Diagnostic.Create(infoDiagDescriptor, Location.None) Dim warningDiag = Microsoft.CodeAnalysis.Diagnostic.Create(warningDiagDescriptor, Location.None) Dim errorDiag = Microsoft.CodeAnalysis.Diagnostic.Create(errorDiagDescriptor, Location.None) Dim diags = New Diagnostic() {noneDiag, infoDiag, warningDiag, errorDiag} ' Escalate all diagnostics to error. Dim specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() specificDiagOptions.Add(noneDiagDescriptor.Id, ReportDiagnostic.[Error]) specificDiagOptions.Add(infoDiagDescriptor.Id, ReportDiagnostic.[Error]) specificDiagOptions.Add(warningDiagDescriptor.Id, ReportDiagnostic.[Error]) Dim options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) Dim comp = CreateCompilationWithMscorlib40({""}, options:=options) Dim effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(diags.Length, effectiveDiags.Length) For Each effectiveDiag In effectiveDiags Assert.True(effectiveDiag.Severity = DiagnosticSeverity.Error) Next ' Suppress all diagnostics. ' NOTE: Diagnostics with default severity error cannot be suppressed and its severity cannot be lowered. specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() specificDiagOptions.Add(noneDiagDescriptor.Id, ReportDiagnostic.Suppress) specificDiagOptions.Add(infoDiagDescriptor.Id, ReportDiagnostic.Suppress) specificDiagOptions.Add(warningDiagDescriptor.Id, ReportDiagnostic.Suppress) specificDiagOptions.Add(errorDiagDescriptor.Id, ReportDiagnostic.Suppress) options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(0, effectiveDiags.Length) ' Shuffle diagnostic severity. specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() specificDiagOptions.Add(noneDiagDescriptor.Id, ReportDiagnostic.Info) specificDiagOptions.Add(infoDiagDescriptor.Id, ReportDiagnostic.Hidden) specificDiagOptions.Add(warningDiagDescriptor.Id, ReportDiagnostic.[Error]) specificDiagOptions.Add(errorDiagDescriptor.Id, ReportDiagnostic.Warn) options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(diags.Length, effectiveDiags.Length) Dim diagIds = New HashSet(Of String)(diags.[Select](Function(d) d.Id)) For Each effectiveDiag In effectiveDiags Assert.[True](diagIds.Remove(effectiveDiag.Id)) Select Case effectiveDiag.Severity Case DiagnosticSeverity.Hidden Assert.Equal(infoDiagDescriptor.Id, effectiveDiag.Id) Case DiagnosticSeverity.Info Assert.Equal(noneDiagDescriptor.Id, effectiveDiag.Id) Exit Select Case DiagnosticSeverity.Warning Assert.Equal(errorDiagDescriptor.Id, effectiveDiag.Id) Exit Select Case DiagnosticSeverity.Error Assert.Equal(warningDiagDescriptor.Id, effectiveDiag.Id) Exit Select Case Else Throw ExceptionUtilities.Unreachable End Select Next Assert.Empty(diagIds) End Sub <Fact> Public Sub TestGetEffectiveDiagnosticsGlobal() Dim noneDiagDescriptor = New DiagnosticDescriptor("XX0001", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Hidden, isEnabledByDefault:=True) Dim infoDiagDescriptor = New DiagnosticDescriptor("XX0002", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Info, isEnabledByDefault:=True) Dim warningDiagDescriptor = New DiagnosticDescriptor("XX0003", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Dim errorDiagDescriptor = New DiagnosticDescriptor("XX0004", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.[Error], isEnabledByDefault:=True) Dim noneDiag = Microsoft.CodeAnalysis.Diagnostic.Create(noneDiagDescriptor, Location.None) Dim infoDiag = Microsoft.CodeAnalysis.Diagnostic.Create(infoDiagDescriptor, Location.None) Dim warningDiag = Microsoft.CodeAnalysis.Diagnostic.Create(warningDiagDescriptor, Location.None) Dim errorDiag = Microsoft.CodeAnalysis.Diagnostic.Create(errorDiagDescriptor, Location.None) Dim diags = New Diagnostic() {noneDiag, infoDiag, warningDiag, errorDiag} Dim options = TestOptions.ReleaseDll.WithGeneralDiagnosticOption(ReportDiagnostic.Default) Dim comp = CreateCompilationWithMscorlib40({""}, options:=options) Dim effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(4, effectiveDiags.Length) options = TestOptions.ReleaseDll.WithGeneralDiagnosticOption(ReportDiagnostic.Error) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(4, effectiveDiags.Length) Assert.Equal(1, effectiveDiags.Count(Function(d) d.IsWarningAsError)) options = TestOptions.ReleaseDll.WithGeneralDiagnosticOption(ReportDiagnostic.Warn) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(4, effectiveDiags.Length) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Error)) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Warning)) options = TestOptions.ReleaseDll.WithGeneralDiagnosticOption(ReportDiagnostic.Info) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(4, effectiveDiags.Length) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Error)) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Info)) options = TestOptions.ReleaseDll.WithGeneralDiagnosticOption(ReportDiagnostic.Hidden) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(4, effectiveDiags.Length) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Error)) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Hidden)) options = TestOptions.ReleaseDll.WithGeneralDiagnosticOption(ReportDiagnostic.Suppress) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(2, effectiveDiags.Length) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Error)) Assert.Equal(1, effectiveDiags.Count(Function(d) d.Severity = DiagnosticSeverity.Hidden)) End Sub <Fact> Public Sub TestDisabledDiagnostics() Dim disabledDiagDescriptor = New DiagnosticDescriptor("XX001", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=False) Dim enabledDiagDescriptor = New DiagnosticDescriptor("XX002", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Dim disabledDiag = CodeAnalysis.Diagnostic.Create(disabledDiagDescriptor, Location.None) Dim enabledDiag = CodeAnalysis.Diagnostic.Create(enabledDiagDescriptor, Location.None) Dim diags = {disabledDiag, enabledDiag} ' Verify that only the enabled diag shows up after filtering. Dim options = TestOptions.ReleaseDll Dim comp = CreateCompilationWithMscorlib40({""}, options:=options) Dim effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(1, effectiveDiags.Length) Assert.Contains(enabledDiag, effectiveDiags) ' If the disabled diag was enabled through options, then it should show up. Dim specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() specificDiagOptions.Add(disabledDiagDescriptor.Id, ReportDiagnostic.Warn) specificDiagOptions.Add(enabledDiagDescriptor.Id, ReportDiagnostic.Suppress) options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) comp = CreateCompilationWithMscorlib40({""}, options:=options) effectiveDiags = comp.GetEffectiveDiagnostics(diags).ToArray() Assert.Equal(1, effectiveDiags.Length) Assert.Contains(disabledDiag, effectiveDiags) End Sub Public Class FullyDisabledAnalyzer Inherits DiagnosticAnalyzer Public Shared desc1 As New DiagnosticDescriptor("XX001", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=False) Public Shared desc2 As New DiagnosticDescriptor("XX002", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=False) Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(desc1, desc2) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) End Sub End Class Public Class PartiallyDisabledAnalyzer Inherits DiagnosticAnalyzer Public Shared desc1 As New DiagnosticDescriptor("XX003", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=False) Public Shared desc2 As New DiagnosticDescriptor("XX004", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(desc1, desc2) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) End Sub End Class <Fact, Obsolete("IsDiagnosticAnalyzerSuppressed is an obsolete public API")> Public Sub TestDisabledAnalyzers() Dim fullyDisabledAnalyzer = New FullyDisabledAnalyzer() Dim partiallyDisabledAnalyzer = New PartiallyDisabledAnalyzer() Dim options = TestOptions.ReleaseDll Assert.True(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) Assert.False(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) Dim specificDiagOptions = New Dictionary(Of String, ReportDiagnostic)() specificDiagOptions.Add(FullyDisabledAnalyzer.desc1.Id, ReportDiagnostic.Warn) specificDiagOptions.Add(PartiallyDisabledAnalyzer.desc2.Id, ReportDiagnostic.Suppress) options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) Assert.False(fullyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) Assert.True(partiallyDisabledAnalyzer.IsDiagnosticAnalyzerSuppressed(options)) End Sub Public Class ModuleStatementAnalyzer Inherits DiagnosticAnalyzer Public Shared desc1 As New DiagnosticDescriptor("XX001", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(desc1) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterSyntaxNodeAction(AddressOf AnalyzeNode, SyntaxKind.ModuleStatement) End Sub Public Sub AnalyzeNode(context As SyntaxNodeAnalysisContext) Dim moduleStatement = DirectCast(context.Node, ModuleStatementSyntax) context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(desc1, context.Node.GetLocation)) End Sub End Class <Fact> Public Sub TestModuleStatementSyntaxAnalyzer() Dim analyzer = New ModuleStatementAnalyzer() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Public Module ThisModule End Module ]]> </file> </compilation> Dim comp = CompilationUtils.CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("XX001", <![CDATA[Public Module ThisModule]]>)) End Sub Public Class MockSymbolAnalyzer Inherits DiagnosticAnalyzer Public Shared desc1 As New DiagnosticDescriptor("XX001", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(desc1) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterSymbolAction(AddressOf AnalyzeSymbol, SymbolKind.NamedType) End Sub Public Sub AnalyzeSymbol(context As SymbolAnalysisContext) Dim sourceLoc = context.Symbol.Locations.First(Function(l) l.IsInSource) context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(desc1, sourceLoc)) End Sub End Class <WorkItem(998724, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/998724")> <Fact> Public Sub TestSymbolAnalyzerNotInvokedForMyTemplateSymbols() Dim analyzer = New MockSymbolAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Public Class C End Class ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) Dim MyTemplate = MyTemplateTests.GetMyTemplateTree(compilation) Assert.NotNull(MyTemplate) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("XX001", <![CDATA[C]]>)) End Sub Public Class NamespaceAndTypeNodeAnalyzer Inherits DiagnosticAnalyzer Public Shared desc1 As New DiagnosticDescriptor("XX001", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(desc1) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterSyntaxNodeAction(AddressOf AnalyzeNode, SyntaxKind.NamespaceBlock, SyntaxKind.ClassBlock) End Sub Public Sub AnalyzeNode(context As SyntaxNodeAnalysisContext) Dim location As Location = Nothing Select Case context.Node.Kind Case SyntaxKind.NamespaceBlock location = DirectCast(context.Node, NamespaceBlockSyntax).NamespaceStatement.Name.GetLocation Case SyntaxKind.ClassBlock location = DirectCast(context.Node, ClassBlockSyntax).BlockStatement.Identifier.GetLocation End Select context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(desc1, location)) End Sub End Class <Fact> Public Sub TestSyntaxAnalyzerInvokedForNamespaceBlockAndClassBlock() Dim analyzer = New NamespaceAndTypeNodeAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Namespace N Public Class C End Class End Namespace ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("XX001", <![CDATA[N]]>), Diagnostic("XX001", <![CDATA[C]]>)) End Sub Private Class CodeBlockAnalyzer Inherits DiagnosticAnalyzer Private Shared ReadOnly s_descriptor As DiagnosticDescriptor = DescriptorFactory.CreateSimpleDescriptor("CodeBlockDiagnostic") Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(s_descriptor) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterCodeBlockAction(AddressOf OnCodeBlock) End Sub Private Shared Sub OnCodeBlock(context As CodeBlockAnalysisContext) context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(s_descriptor, context.OwningSymbol.DeclaringSyntaxReferences.First.GetLocation)) End Sub End Class <Fact, WorkItem(1008059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1008059")> Public Sub TestCodeBlockAnalyzersForNoExecutableCode() Dim analyzer = New CodeBlockAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Public MustInherit Class C Public Property P() As Integer Public field As Integer Public MustOverride Sub Method() End Class ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}) End Sub <Fact, WorkItem(1008059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1008059")> Public Sub TestCodeBlockAnalyzersForEmptyMethodBody() Dim analyzer = New CodeBlockAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Public Class C Public Sub Method() End Sub End Class ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("CodeBlockDiagnostic", <![CDATA[Public Sub Method()]]>)) End Sub <Fact, WorkItem(1096600, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1096600")> Private Sub TestDescriptorForConfigurableCompilerDiagnostics() ' Verify that all configurable compiler diagnostics, i.e. all non-error diagnostics, ' have a non-null and non-empty Title and Category. ' These diagnostic descriptor fields show up in the ruleset editor and hence must have a valid value. Dim analyzer = New VisualBasicCompilerDiagnosticAnalyzer() For Each descriptor In analyzer.SupportedDiagnostics Assert.Equal(descriptor.IsEnabledByDefault, True) If descriptor.IsNotConfigurable() Then Continue For End If Dim title = descriptor.Title.ToString() If String.IsNullOrEmpty(title) Then Dim id = Integer.Parse(descriptor.Id.Substring(2)) Dim missingResource = [Enum].GetName(GetType(ERRID), id) & "_Title" Dim message = String.Format("Add resource string named '{0}' for Title of '{1}' to '{2}'", missingResource, descriptor.Id, NameOf(VBResources)) ' This assert will fire if you are adding a new compiler diagnostic (non-error severity), ' but did not add a title resource string for the diagnostic. Assert.Fail(message) End If Dim category = descriptor.Category If String.IsNullOrEmpty(title) Then Dim message = String.Format("'{0}' must have a non-null non-empty 'Category'", descriptor.Id) Assert.Fail(message) End If Next End Sub Public Class FieldSymbolAnalyzer Inherits DiagnosticAnalyzer Public Shared desc1 As New DiagnosticDescriptor("FieldSymbolDiagnostic", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(desc1) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterSymbolAction(AddressOf AnalyzeSymbol, SymbolKind.Field) End Sub Public Sub AnalyzeSymbol(context As SymbolAnalysisContext) Dim sourceLoc = context.Symbol.Locations.First(Function(l) l.IsInSource) context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(desc1, sourceLoc)) End Sub End Class <Fact, WorkItem(1109126, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109126")> Public Sub TestFieldSymbolAnalyzer_EnumField() Dim analyzer = New FieldSymbolAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Public Enum E X = 0 End Enum ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("FieldSymbolDiagnostic", <![CDATA[X]]>)) End Sub <Fact, WorkItem(1111667, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1111667")> Public Sub TestFieldSymbolAnalyzer_FieldWithoutInitializer() Dim analyzer = New FieldSymbolAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Public Class TestClass Public Field As System.IntPtr End Class ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("FieldSymbolDiagnostic", <![CDATA[Field]]>)) End Sub Public Class FieldDeclarationAnalyzer Inherits DiagnosticAnalyzer Public Shared desc1 As New DiagnosticDescriptor("FieldDeclarationDiagnostic", "DummyDescription", "DummyMessage", "DummyCategory", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(desc1) End Get End Property Public Overrides Sub Initialize(context As AnalysisContext) context.RegisterSyntaxNodeAction(AddressOf AnalyzeNode, SyntaxKind.FieldDeclaration) End Sub Public Sub AnalyzeNode(context As SyntaxNodeAnalysisContext) Dim sourceLoc = DirectCast(context.Node, FieldDeclarationSyntax).GetLocation context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(desc1, sourceLoc)) End Sub End Class <Fact, WorkItem(565, "https://github.com/dotnet/roslyn/issues/565")> Public Sub TestFieldDeclarationAnalyzer() Dim analyzer = New FieldDeclarationAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Public Class C Dim x, y As Integer Dim z As Integer Dim x2 = 0, y2 = 0 Dim z2 = 0 End Class ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("FieldDeclarationDiagnostic", <![CDATA[Dim x, y As Integer]]>), Diagnostic("FieldDeclarationDiagnostic", <![CDATA[Dim z As Integer]]>), Diagnostic("FieldDeclarationDiagnostic", <![CDATA[Dim x2 = 0, y2 = 0]]>), Diagnostic("FieldDeclarationDiagnostic", <![CDATA[Dim z2 = 0]]>)) End Sub <Fact, WorkItem(4745, "https://github.com/dotnet/roslyn/issues/4745")> Public Sub TestNamespaceDeclarationAnalyzer() Dim analyzer = New VisualBasicNamespaceDeclarationAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Namespace Goo.Bar.GooBar End Namespace ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic(VisualBasicNamespaceDeclarationAnalyzer.DiagnosticId, <![CDATA[Namespace Goo.Bar.GooBar]]>)) End Sub <Fact, WorkItem(5463, "https://github.com/dotnet/roslyn/issues/5463")> Public Sub TestObjectCreationInCodeBlockAnalyzer() Dim analyzer = New VisualBasicCodeBlockObjectCreationAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Public Class C1 End Class Public Class C2 End Class Public Class C3 End Class Public Class D Dim x As C1 = New C1() Dim y As New C2() Public ReadOnly Property Z As New C3() End Class ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=TestOptions.ReleaseDll) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic(VisualBasicCodeBlockObjectCreationAnalyzer.DiagnosticDescriptor.Id, <![CDATA[New C1()]]>), Diagnostic(VisualBasicCodeBlockObjectCreationAnalyzer.DiagnosticDescriptor.Id, <![CDATA[New C2()]]>), Diagnostic(VisualBasicCodeBlockObjectCreationAnalyzer.DiagnosticDescriptor.Id, <![CDATA[New C3()]]>)) End Sub <Fact, WorkItem(1473, "https://github.com/dotnet/roslyn/issues/1473")> Public Sub TestReportingNotConfigurableDiagnostic() Dim analyzer = New NotConfigurableDiagnosticAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[]]> </file> </compilation> ' Verify, not configurable enabled diagnostic is always reported and disabled diagnostic is never reported.. Dim options = TestOptions.ReleaseDll Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=options) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic(NotConfigurableDiagnosticAnalyzer.EnabledRule.Id)) ' Verify not configurable enabled diagnostic cannot be suppressed. Dim specificDiagOptions = New Dictionary(Of String, ReportDiagnostic) specificDiagOptions.Add(NotConfigurableDiagnosticAnalyzer.EnabledRule.Id, ReportDiagnostic.Suppress) options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=options) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic(NotConfigurableDiagnosticAnalyzer.EnabledRule.Id)) ' Verify not configurable disabled diagnostic cannot be enabled. specificDiagOptions.Clear() specificDiagOptions.Add(NotConfigurableDiagnosticAnalyzer.DisabledRule.Id, ReportDiagnostic.Warn) options = TestOptions.ReleaseDll.WithSpecificDiagnosticOptions(specificDiagOptions) compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}, options:=options) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic(NotConfigurableDiagnosticAnalyzer.EnabledRule.Id)) End Sub <Fact, WorkItem(1709, "https://github.com/dotnet/roslyn/issues/1709")> Public Sub TestCodeBlockAction() Dim analyzer = New CodeBlockActionAnalyzer() Dim sources = <compilation> <file name="c.vb"> <![CDATA[ Class C Public Sub M() End Sub End Class ]]> </file> </compilation> Dim compilation = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic(CodeBlockActionAnalyzer.CodeBlockTopLevelRule.Id, <![CDATA[M]]>).WithArguments("M"), Diagnostic(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 = CreateCompilationWithMscorlib40AndReferences(sources, references:={SystemCoreRef, MsvbRef}) compilation.VerifyDiagnostics() compilation.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic(CodeBlockActionAnalyzer.CodeBlockTopLevelRule.Id, <![CDATA[M]]>).WithArguments("M")) End Sub Private Shared Sub TestEffectiveSeverity(defaultSeverity As DiagnosticSeverity, expectedEffectiveSeverity As ReportDiagnostic, Optional specificOptions As Dictionary(Of String, ReportDiagnostic) = Nothing, Optional generalOption As ReportDiagnostic = ReportDiagnostic.Default, Optional isEnabledByDefault As Boolean = True) specificOptions = If(specificOptions, New Dictionary(Of String, ReportDiagnostic)) Dim options = New VisualBasicCompilationOptions(OutputKind.ConsoleApplication, generalDiagnosticOption:=generalOption, specificDiagnosticOptions:=specificOptions) Dim descriptor = New DiagnosticDescriptor(id:="Test0001", title:="Test0001", messageFormat:="Test0001", category:="Test0001", defaultSeverity:=defaultSeverity, isEnabledByDefault:=isEnabledByDefault) Dim effectiveSeverity = descriptor.GetEffectiveSeverity(options) Assert.Equal(expectedEffectiveSeverity, effectiveSeverity) End Sub <Fact> <WorkItem(1107500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1107500")> <WorkItem(2598, "https://github.com/dotnet/roslyn/issues/2598")> Public Sub EffectiveSeverity_DiagnosticDefault1() TestEffectiveSeverity(DiagnosticSeverity.Warning, ReportDiagnostic.Warn) End Sub <Fact> <WorkItem(1107500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1107500")> <WorkItem(2598, "https://github.com/dotnet/roslyn/issues/2598")> Public Sub EffectiveSeverity_DiagnosticDefault2() Dim specificOptions = New Dictionary(Of String, ReportDiagnostic) From {{"Test0001", ReportDiagnostic.Default}} Dim generalOption = ReportDiagnostic.Error TestEffectiveSeverity(DiagnosticSeverity.Warning, expectedEffectiveSeverity:=ReportDiagnostic.Warn, specificOptions:=specificOptions, generalOption:=generalOption) End Sub <Fact> <WorkItem(1107500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1107500")> <WorkItem(2598, "https://github.com/dotnet/roslyn/issues/2598")> Public Sub EffectiveSeverity_GeneralOption() Dim generalOption = ReportDiagnostic.Error TestEffectiveSeverity(DiagnosticSeverity.Warning, expectedEffectiveSeverity:=generalOption, generalOption:=generalOption) End Sub <Fact> <WorkItem(1107500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1107500")> <WorkItem(2598, "https://github.com/dotnet/roslyn/issues/2598")> Public Sub EffectiveSeverity_SpecificOption() Dim specificOption = ReportDiagnostic.Suppress Dim specificOptions = New Dictionary(Of String, ReportDiagnostic) From {{"Test0001", specificOption}} Dim generalOption = ReportDiagnostic.Error TestEffectiveSeverity(DiagnosticSeverity.Warning, expectedEffectiveSeverity:=specificOption, specificOptions:=specificOptions, generalOption:=generalOption) End Sub <Fact> <WorkItem(1107500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1107500")> <WorkItem(2598, "https://github.com/dotnet/roslyn/issues/2598")> Public Sub EffectiveSeverity_GeneralOptionDoesNotEnableDisabledDiagnostic() Dim generalOption = ReportDiagnostic.Error Dim enabledByDefault = False TestEffectiveSeverity(DiagnosticSeverity.Warning, expectedEffectiveSeverity:=ReportDiagnostic.Suppress, generalOption:=generalOption, isEnabledByDefault:=enabledByDefault) End Sub <Fact> <WorkItem(1107500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1107500")> <WorkItem(2598, "https://github.com/dotnet/roslyn/issues/2598")> Public Sub EffectiveSeverity_SpecificOptionEnablesDisabledDiagnostic() Dim specificOption = ReportDiagnostic.Warn Dim specificOptions = New Dictionary(Of String, ReportDiagnostic) From {{"Test0001", specificOption}} Dim generalOption = ReportDiagnostic.Error Dim enabledByDefault = False TestEffectiveSeverity(DiagnosticSeverity.Warning, expectedEffectiveSeverity:=specificOption, specificOptions:=specificOptions, generalOption:=generalOption, isEnabledByDefault:=enabledByDefault) End Sub <Fact, WorkItem(6998, "https://github.com/dotnet/roslyn/issues/6998")> Public Sub TestGeneratedCodeAnalyzer() Dim source = <![CDATA[ <System.CodeDom.Compiler.GeneratedCodeAttribute("tool", "version")> _ Class GeneratedCode{0} Private Class Nested{0} Private Sub NestedMethod() System.Console.WriteLine(0) End Sub End Class Private Sub GeneratedCodeMethod() System.Console.WriteLine(0) End Sub End Class Class NonGeneratedCode{0} <System.CodeDom.Compiler.GeneratedCodeAttribute("tool", "version")> _ Private Class NestedGeneratedCode{0} Private Sub NestedGeneratedCodeMethod() System.Console.WriteLine(0) End Sub End Class Private Sub NonGeneratedCodeMethod() System.Console.WriteLine(0) End Sub End Class ]]>.Value Dim generatedFileNames = {"TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.vb", "Test.designer.vb", "Test.Designer.vb", "Test.generated.vb", "Test.g.vb", "Test.g.i.vb"} Dim builder = ImmutableArray.CreateBuilder(Of SyntaxTree)() Dim treeNum As Integer = 0 ' Trees with non-generated code file names Dim tree = VisualBasicSyntaxTree.ParseText(String.Format(source, treeNum), path:="SourceFileRegular.vb") builder.Add(tree) treeNum = treeNum + 1 tree = VisualBasicSyntaxTree.ParseText(String.Format(source, treeNum), path:="AssemblyInfo.vb") builder.Add(tree) treeNum = treeNum + 1 ' Trees with generated code file names For Each fileName In generatedFileNames tree = VisualBasicSyntaxTree.ParseText(String.Format(source, treeNum), path:=fileName) builder.Add(tree) treeNum = treeNum + 1 Next ' Tree with '<auto-generated>' comment Dim autoGeneratedPrefixes = {"' <auto-generated> ", "' <autogenerated> "} For i = 0 To autoGeneratedPrefixes.Length - 1 Dim autoGeneratedPrefix = autoGeneratedPrefixes(i) tree = VisualBasicSyntaxTree.ParseText(String.Format(autoGeneratedPrefix + source, treeNum), path:=$"SourceFileWithAutoGeneratedComment{i}.vb") builder.Add(tree) treeNum = treeNum + 1 Next ' Verify no compiler diagnostics. Dim trees = builder.ToImmutable() Dim compilation = CreateCompilationWithMscorlib461(trees.ToArray(), {SystemRef}, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() Dim isGeneratedFile As Func(Of String, Boolean) = Function(fileName) fileName.Contains("SourceFileWithAutoGeneratedComment") OrElse generatedFileNames.Contains(fileName) ' (1) Verify default mode of analysis when there is no generated code configuration. VerifyGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFile, generatedCodeAnalysisFlagsOpt:=Nothing) ' (2) Verify ConfigureGeneratedCodeAnalysis with different combinations of GeneratedCodeAnalysisFlags. VerifyGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFile, GeneratedCodeAnalysisFlags.None) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFile, AnalyzerDriver.DefaultGeneratedCodeAnalysisFlags) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFile, GeneratedCodeAnalysisFlags.Analyze) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFile, GeneratedCodeAnalysisFlags.ReportDiagnostics) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFile, GeneratedCodeAnalysisFlags.Analyze Or GeneratedCodeAnalysisFlags.ReportDiagnostics) ' (4) Ensure warnaserror doesn't produce noise in generated files. Dim options = compilation.Options.WithGeneralDiagnosticOption(ReportDiagnostic.Error) Dim warnAsErrorCompilation = compilation.WithOptions(options) VerifyGeneratedCodeAnalyzerDiagnostics(warnAsErrorCompilation, isGeneratedFile, generatedCodeAnalysisFlagsOpt:=Nothing) End Sub <Fact, WorkItem(6998, "https://github.com/dotnet/roslyn/issues/6998")> Public Sub TestGeneratedCodeAnalyzerPartialType() Dim source As String = <![CDATA[' <System.CodeDom.Compiler.GeneratedCodeAttribute("tool", "version")> _ Partial Class PartialType End Class Partial Class PartialType End Class ]]>.Value Dim tree = VisualBasicSyntaxTree.ParseText(source, path:="SourceFileRegular.vb") Dim compilation = CreateCompilationWithMscorlib461({tree}, {SystemRef}, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() Dim builder = ArrayBuilder(Of DiagnosticDescription).GetInstance() ' Expected symbol diagnostics Dim squiggledText = "PartialType" Dim diagnosticArgument = squiggledText Dim line = 3 Dim column = 15 AddExpectedLocalDiagnostics(builder, False, squiggledText, line, column, GeneratedCodeAnalysisFlags.ReportDiagnostics, diagnosticArgument) ' Expected tree diagnostics squiggledText = "Class" diagnosticArgument = tree.FilePath line = 7 column = 5 AddExpectedLocalDiagnostics(builder, False, squiggledText, line, column, GeneratedCodeAnalysisFlags.ReportDiagnostics, diagnosticArgument) ' Expected compilation diagnostics AddExpectedNonLocalDiagnostic(builder, GeneratedCodeAnalyzer.Summary, "PartialType(IsGeneratedCode:False)", $"{compilation.SyntaxTrees(0).FilePath}(IsGeneratedCode:False)") Dim expected = builder.ToArrayAndFree() VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, generatedCodeAnalysisFlagsOpt:=Nothing) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, GeneratedCodeAnalysisFlags.None) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, AnalyzerDriver.DefaultGeneratedCodeAnalysisFlags) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, GeneratedCodeAnalysisFlags.Analyze) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, GeneratedCodeAnalysisFlags.ReportDiagnostics) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, GeneratedCodeAnalysisFlags.Analyze Or GeneratedCodeAnalysisFlags.ReportDiagnostics) End Sub Friend Class OwningSymbolTestAnalyzer Inherits DiagnosticAnalyzer Public Shared ReadOnly ExpressionDescriptor As New DiagnosticDescriptor("Expression", "Expression", "Expression found.", "Testing", DiagnosticSeverity.Warning, isEnabledByDefault:=True) Public NotOverridable Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(ExpressionDescriptor) End Get End Property Public NotOverridable Overrides Sub Initialize(context As AnalysisContext) context.RegisterSyntaxNodeAction( Sub(nodeContext) If nodeContext.ContainingSymbol.Name.StartsWith("Funky") AndAlso nodeContext.Compilation.Language = "Visual Basic" Then nodeContext.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(ExpressionDescriptor, nodeContext.Node.GetLocation())) End If End Sub, SyntaxKind.IdentifierName, SyntaxKind.NumericLiteralExpression) End Sub End Class <Fact> Public Sub OwningSymbolVisualBasic() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Public Sub UnFunkyMethod() Dim x As Integer = 0 Dim y As Integer = x End Sub Public Sub FunkyMethod() Dim x As Integer = 0 Dim y As Integer = x End Sub Public FunkyField As Integer = 12 Public UnFunkyField As Integer = 12 End Class ]]> </file> </compilation> Dim comp = CompilationUtils.CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New OwningSymbolTestAnalyzer}, Nothing, Nothing, Diagnostic(OwningSymbolTestAnalyzer.ExpressionDescriptor.Id, "0").WithLocation(8, 28), Diagnostic(OwningSymbolTestAnalyzer.ExpressionDescriptor.Id, "x").WithLocation(9, 28), Diagnostic(OwningSymbolTestAnalyzer.ExpressionDescriptor.Id, "12").WithLocation(12, 36)) End Sub <Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")> Public Sub TestParametersAnalyzer_InRegularMethods() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Public Sub M(a As Integer, b As String) End Sub End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, Diagnostic("Parameter_ID", "a").WithLocation(2, 18), Diagnostic("Parameter_ID", "b").WithLocation(2, 32)) End Sub <Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")> Public Sub TestParametersAnalyzer_InConstructors() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Public Sub New(a As Integer, b As String) End Sub End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, Diagnostic("Parameter_ID", "a").WithLocation(2, 20), Diagnostic("Parameter_ID", "b").WithLocation(2, 34)) End Sub <Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")> Public Sub TestParametersAnalyzer_InIndexers() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Default Public Property Item(a As Integer, b As Integer) As Integer Get Return 0 End Get Set(ByVal Value As Integer) End Set End Property End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, Diagnostic("Parameter_ID", "a").WithLocation(2, 34), Diagnostic("Parameter_ID", "b").WithLocation(2, 48), Diagnostic("Parameter_ID", "Value").WithLocation(6, 19)) End Sub <Fact(Skip:="https://github.com/dotnet/roslyn/issues/14062"), WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")> Public Sub TestParametersAnalyzer_InDelegateTypes() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Delegate Sub DelegateType(a As Integer, b As String) End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, Diagnostic("Parameter_ID", "a").WithLocation(2, 34), Diagnostic("Parameter_ID", "b").WithLocation(2, 48)) End Sub <Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")> Public Sub TestParametersAnalyzer_InOperators() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Public Shared Operator +(ByVal h1 As C, ByVal h2 As C) Return New C() End Operator End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, Diagnostic("Parameter_ID", "h1").WithLocation(2, 36), Diagnostic("Parameter_ID", "h2").WithLocation(2, 51)) End Sub <Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")> Public Sub TestParametersAnalyzer_InInterfaceImplementations() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Interface I Sub M(a As Integer, b As String) End Interface Class C Implements I Public Sub M(a As Integer, b As String) Implements I.M End Sub End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, Diagnostic("Parameter_ID", "a").WithLocation(2, 11), Diagnostic("Parameter_ID", "b").WithLocation(2, 25), Diagnostic("Parameter_ID", "a").WithLocation(7, 18), Diagnostic("Parameter_ID", "b").WithLocation(7, 32)) End Sub <Fact, WorkItem(8753, "https://github.com/dotnet/roslyn/issues/8753")> Public Sub TestParametersAnalyzer_InParameterizedProperties() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Public ReadOnly Property Test(a As Integer, b As String) As Integer Get Return 1 End Get End Property End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() comp.VerifyAnalyzerDiagnostics({New AnalyzerForParameters}, Nothing, Nothing, Diagnostic("Parameter_ID", "a").WithLocation(2, 35), Diagnostic("Parameter_ID", "b").WithLocation(2, 49)) End Sub Private Shared Sub VerifyGeneratedCodeAnalyzerDiagnostics(compilation As Compilation, isGeneratedFileName As Func(Of String, Boolean), generatedCodeAnalysisFlagsOpt As GeneratedCodeAnalysisFlags?) Dim expected = GetExpectedGeneratedCodeAnalyzerDiagnostics(compilation, isGeneratedFileName, generatedCodeAnalysisFlagsOpt) VerifyGeneratedCodeAnalyzerDiagnostics(compilation, expected, generatedCodeAnalysisFlagsOpt, testIsGeneratedCodeInCallbacks:=True) End Sub Private Shared Sub VerifyGeneratedCodeAnalyzerDiagnostics(compilation As Compilation, expected As DiagnosticDescription(), generatedCodeAnalysisFlagsOpt As GeneratedCodeAnalysisFlags?, Optional testIsGeneratedCodeInCallbacks As Boolean = False) Dim analyzers = New DiagnosticAnalyzer() {New GeneratedCodeAnalyzer(generatedCodeAnalysisFlagsOpt, testIsGeneratedCodeInCallbacks)} compilation.VerifyAnalyzerDiagnostics(analyzers, Nothing, Nothing, expected) End Sub Private Shared Function GetExpectedGeneratedCodeAnalyzerDiagnostics(compilation As Compilation, isGeneratedFileName As Func(Of String, Boolean), generatedCodeAnalysisFlagsOpt As GeneratedCodeAnalysisFlags?) As DiagnosticDescription() Dim analyzers = New DiagnosticAnalyzer() {New GeneratedCodeAnalyzer(generatedCodeAnalysisFlagsOpt, testIsGeneratedCodeInCallbacks:=True)} Dim files = compilation.SyntaxTrees.Select(Function(t) t.FilePath).ToImmutableArray() Dim sortedCallbackSymbolNames = New SortedSet(Of String)() Dim sortedCallbackTreePaths = New SortedSet(Of String)() Dim sortedCallbackSyntaxNodeNames = New SortedSet(Of String)() Dim sortedCallbackOperationNames = New SortedSet(Of String)() Dim sortedCallbackSemanticModelPaths = New SortedSet(Of String)() Dim sortedCallbackSymbolStartNames = New SortedSet(Of String)() Dim sortedCallbackSymbolEndNames = New SortedSet(Of String)() Dim sortedCallbackOperationBlockStartNames = New SortedSet(Of String)() Dim sortedCallbackOperationBlockEndNames = New SortedSet(Of String)() Dim sortedCallbackOperationBlockNames = New SortedSet(Of String)() Dim sortedCallbackCodeBlockStartNames = New SortedSet(Of String)() Dim sortedCallbackCodeBlockEndNames = New SortedSet(Of String)() Dim sortedCallbackCodeBlockNames = New SortedSet(Of String)() Dim builder = ArrayBuilder(Of DiagnosticDescription).GetInstance() For i As Integer = 0 To compilation.SyntaxTrees.Count() - 1 Dim file = files(i) Dim isGeneratedFile = isGeneratedFileName(file) ' Type "GeneratedCode{0}" Dim squiggledText = String.Format("GeneratedCode{0}", i) Dim diagnosticArgument = squiggledText Dim line = 3 Dim column = 7 Dim isGeneratedCode = True AddExpectedLocalDiagnostics(builder, isGeneratedCode, squiggledText, line, column, generatedCodeAnalysisFlagsOpt, diagnosticArgument) ' Type "Nested{0}" squiggledText = String.Format("Nested{0}", i) diagnosticArgument = squiggledText line = 4 column = 16 isGeneratedCode = True AddExpectedLocalDiagnostics(builder, isGeneratedCode, squiggledText, line, column, generatedCodeAnalysisFlagsOpt, diagnosticArgument) ' Type "NonGeneratedCode{0}" squiggledText = String.Format("NonGeneratedCode{0}", i) diagnosticArgument = squiggledText line = 15 column = 7 isGeneratedCode = isGeneratedFile AddExpectedLocalDiagnostics(builder, isGeneratedCode, squiggledText, line, column, generatedCodeAnalysisFlagsOpt, diagnosticArgument) ' Type "NestedGeneratedCode{0}" squiggledText = String.Format("NestedGeneratedCode{0}", i) diagnosticArgument = squiggledText line = 17 column = 16 isGeneratedCode = True AddExpectedLocalDiagnostics(builder, isGeneratedCode, squiggledText, line, column, generatedCodeAnalysisFlagsOpt, diagnosticArgument) ' File diagnostic squiggledText = "Class" ' last token in file. diagnosticArgument = file line = 26 column = 5 isGeneratedCode = isGeneratedFile AddExpectedLocalDiagnostics(builder, isGeneratedCode, squiggledText, line, column, generatedCodeAnalysisFlagsOpt, diagnosticArgument) ' Compilation end summary diagnostic (verify callbacks into analyzer) ' Analyzer always called for generated code, unless generated code analysis is explicitly disabled. Dim addNames As Action(Of SortedSet(Of String)) = Nothing Dim addPath As Action(Of SortedSet(Of String)) = Nothing Dim index = i If generatedCodeAnalysisFlagsOpt Is Nothing OrElse (generatedCodeAnalysisFlagsOpt And GeneratedCodeAnalysisFlags.Analyze) <> 0 Then addNames = Sub(names As SortedSet(Of String)) names.Add(String.Format("GeneratedCode{0}(IsGeneratedCode:True)", index)) names.Add(String.Format("Nested{0}(IsGeneratedCode:True)", index)) names.Add(String.Format("NonGeneratedCode{0}(IsGeneratedCode:{1})", index, isGeneratedFile)) names.Add(String.Format("NestedGeneratedCode{0}(IsGeneratedCode:True)", index)) End Sub addPath = Sub(paths As SortedSet(Of String)) paths.Add($"{file}(IsGeneratedCode:{isGeneratedFile})") End Sub ElseIf Not isGeneratedFile Then ' Analyzer always called for non-generated code. addNames = Sub(names As SortedSet(Of String)) names.Add(String.Format("NonGeneratedCode{0}(IsGeneratedCode:False)", index)) End Sub addPath = Sub(paths As SortedSet(Of String)) paths.Add($"{file}(IsGeneratedCode:False)") End Sub End If If addNames IsNot Nothing Then addNames(sortedCallbackSymbolNames) addNames(sortedCallbackSyntaxNodeNames) addNames(sortedCallbackSymbolStartNames) addNames(sortedCallbackSymbolEndNames) addNames(sortedCallbackOperationNames) addNames(sortedCallbackOperationBlockStartNames) addNames(sortedCallbackOperationBlockEndNames) addNames(sortedCallbackOperationBlockNames) addNames(sortedCallbackCodeBlockStartNames) addNames(sortedCallbackCodeBlockEndNames) addNames(sortedCallbackCodeBlockNames) End If If addPath IsNot Nothing Then addPath(sortedCallbackTreePaths) addPath(sortedCallbackSemanticModelPaths) End If Next ' Compilation end summary diagnostic (verify callbacks into analyzer) Dim arg1 = sortedCallbackSymbolNames.Join(",") Dim arg2 = sortedCallbackTreePaths.Join(",") Dim arg3 = sortedCallbackSyntaxNodeNames.Join(",") + ";" + sortedCallbackOperationNames.Join(",") + ";" + sortedCallbackSemanticModelPaths.Join(",") + ";" + sortedCallbackSymbolStartNames.Join(",") + ";" + sortedCallbackSymbolEndNames.Join(",") + ";" + sortedCallbackOperationBlockStartNames.Join(",") + ";" + sortedCallbackOperationBlockEndNames.Join(",") + ";" + sortedCallbackOperationBlockNames.Join(",") + ";" + sortedCallbackCodeBlockStartNames.Join(",") + ";" + sortedCallbackCodeBlockEndNames.Join(",") + ";" + sortedCallbackCodeBlockNames.Join(",") AddExpectedNonLocalDiagnostic(builder, GeneratedCodeAnalyzer.Summary2, {arg1, arg2, arg3}) If compilation.Options.GeneralDiagnosticOption = ReportDiagnostic.Error Then For i As Integer = 0 To builder.Count - 1 If DirectCast(builder(i).Code, String) <> GeneratedCodeAnalyzer.Error.Id Then builder(i) = builder(i).WithWarningAsError(True) End If Next End If Return builder.ToArrayAndFree() End Function Private Shared Sub AddExpectedLocalDiagnostics( builder As ArrayBuilder(Of DiagnosticDescription), isGeneratedCode As Boolean, squiggledText As String, line As Integer, column As Integer, generatedCodeAnalysisFlagsOpt As GeneratedCodeAnalysisFlags?, ParamArray arguments As String()) ' Always report diagnostics in generated code, unless explicitly suppressed or we are not even analyzing generated code. Dim reportInGeneratedCode = generatedCodeAnalysisFlagsOpt Is Nothing OrElse ((generatedCodeAnalysisFlagsOpt.GetValueOrDefault() And GeneratedCodeAnalysisFlags.ReportDiagnostics) <> 0 AndAlso (generatedCodeAnalysisFlagsOpt.GetValueOrDefault() And GeneratedCodeAnalysisFlags.Analyze) <> 0) If Not isGeneratedCode OrElse reportInGeneratedCode Then Dim diag = Diagnostic(GeneratedCodeAnalyzer.Warning.Id, squiggledText).WithArguments(arguments).WithLocation(line, column) builder.Add(diag) diag = Diagnostic(GeneratedCodeAnalyzer.Error.Id, squiggledText).WithArguments(arguments).WithLocation(line, column) builder.Add(diag) End If End Sub Private Shared Sub AddExpectedNonLocalDiagnostic(builder As ArrayBuilder(Of DiagnosticDescription), descriptor As DiagnosticDescriptor, ParamArray arguments As String()) AddExpectedDiagnostic(builder, descriptor.Id, Nothing, 1, 1, arguments) End Sub Private Shared Sub AddExpectedDiagnostic(builder As ArrayBuilder(Of DiagnosticDescription), diagnosticId As String, squiggledText As String, line As Integer, column As Integer, ParamArray arguments As String()) Dim diag = Diagnostic(diagnosticId, squiggledText).WithArguments(arguments).WithLocation(line, column) builder.Add(diag) End Sub <DiagnosticAnalyzer(LanguageNames.VisualBasic)> Friend NotInheritable Class GeneratedCodeAnalyzer Inherits AbstractGeneratedCodeAnalyzer(Of SyntaxKind) Public Sub New(generatedCodeAnalysisFlags As GeneratedCodeAnalysisFlags?, Optional testIsGeneratedCodeInCallbacks As Boolean = False) MyBase.New(generatedCodeAnalysisFlags, testIsGeneratedCodeInCallbacks) End Sub Protected Overrides ReadOnly Property ClassDeclarationSyntaxKind As SyntaxKind Get Return SyntaxKind.ClassBlock End Get End Property End Class <Fact, WorkItem(23309, "https://github.com/dotnet/roslyn/issues/23309")> Public Sub TestFieldReferenceAnalyzer_InAttributes() Dim source = <compilation> <file name="c.vb"> <> p1 As Integer) <MyAttribute(FieldForDelegateFunction)> Public Delegate Function Delegate2(<MyAttribute(FieldForDelegateFunctionParameter)> p1 As Integer) As <MyAttribute(FieldForDelegateFunctionReturnType)> Integer <MyAttribute(FieldForEventField)> Public Event MyEvent(<MyAttribute(FieldForEventParameter)> p1 As Integer) <MyAttribute(FieldForEvent)> Private Custom Event MyEvent2 As EventHandler Implements MyInterface.MyEvent <MyAttribute(FieldForAddHandler)> AddHandler(ByVal value As EventHandler) End AddHandler <MyAttribute(FieldForRemoveHandler)> RemoveHandler(ByVal value As EventHandler) End RemoveHandler <MyAttribute(FieldForRaiseHandler)> RaiseEvent() End RaiseEvent End Event <MyAttribute(FieldForProperty)> Private Property P1() As <MyAttribute(FieldForPropertyReturnType)> Integer <MyAttribute(FieldForPropertyGetter)> Get Return 0 End Get <MyAttribute(FieldForPropertySetter)> Set End Set End Property <MyAttribute(FieldForIndexer)> Default Property Item(<MyAttribute(FieldForIndexerParameter)> index As Integer) As <MyAttribute(FieldForIndexerReturnType)> Integer <MyAttribute(FieldForIndexerGetter)> Get Return 0 End Get <MyAttribute(FieldForIndexerSetter)> Set End Set End Property End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() ' Test RegisterOperationBlockAction TestFieldReferenceAnalyzer_InAttributes_Core(comp, doOperationBlockAnalysis:=True) ' Test RegisterOperationAction TestFieldReferenceAnalyzer_InAttributes_Core(comp, doOperationBlockAnalysis:=False) End Sub Private Shared Sub TestFieldReferenceAnalyzer_InAttributes_Core(comp As Compilation, doOperationBlockAnalysis As Boolean) comp.VerifyAnalyzerDiagnostics({New FieldReferenceOperationAnalyzer(doOperationBlockAnalysis)}, Nothing, Nothing, Diagnostic("ID", "C.FieldForClass").WithArguments("FieldForClass", "1").WithLocation(16, 14), Diagnostic("ID", "FieldForStruct").WithArguments("FieldForStruct", "2").WithLocation(27, 18), Diagnostic("ID", "FieldForInterface").WithArguments("FieldForInterface", "3").WithLocation(31, 18), Diagnostic("ID", "FieldForField").WithArguments("FieldForField", "4").WithLocation(35, 18), Diagnostic("ID", "FieldForField").WithArguments("FieldForField", "4").WithLocation(35, 18), Diagnostic("ID", "FieldForMethod").WithArguments("FieldForMethod", "5").WithLocation(38, 18), Diagnostic("ID", "FieldForEnum").WithArguments("FieldForEnum", "6").WithLocation(43, 18), Diagnostic("ID", "FieldForEnumMember").WithArguments("FieldForEnumMember", "7").WithLocation(45, 22), Diagnostic("ID", "FieldForDelegateSub").WithArguments("FieldForDelegateSub", "8").WithLocation(49, 18), Diagnostic("ID", "FieldForDelegateFunction").WithArguments("FieldForDelegateFunction", "9").WithLocation(52, 18), Diagnostic("ID", "FieldForEventField").WithArguments("FieldForEventField", "10").WithLocation(55, 18), Diagnostic("ID", "FieldForEvent").WithArguments("FieldForEvent", "11").WithLocation(58, 18), Diagnostic("ID", "FieldForAddHandler").WithArguments("FieldForAddHandler", "12").WithLocation(60, 22), Diagnostic("ID", "FieldForRemoveHandler").WithArguments("FieldForRemoveHandler", "13").WithLocation(63, 22), Diagnostic("ID", "FieldForRaiseHandler").WithArguments("FieldForRaiseHandler", "14").WithLocation(66, 22), Diagnostic("ID", "FieldForProperty").WithArguments("FieldForProperty", "15").WithLocation(71, 18), Diagnostic("ID", "FieldForPropertyGetter").WithArguments("FieldForPropertyGetter", "16").WithLocation(73, 22), Diagnostic("ID", "FieldForPropertySetter").WithArguments("FieldForPropertySetter", "17").WithLocation(77, 22), Diagnostic("ID", "FieldForIndexer").WithArguments("FieldForIndexer", "18").WithLocation(82, 18), Diagnostic("ID", "FieldForIndexerGetter").WithArguments("FieldForIndexerGetter", "19").WithLocation(84, 22), Diagnostic("ID", "FieldForIndexerSetter").WithArguments("FieldForIndexerSetter", "20").WithLocation(88, 22), Diagnostic("ID", "FieldForMethodParameter").WithArguments("FieldForMethodParameter", "21").WithLocation(39, 38), Diagnostic("ID", "FieldForEventParameter").WithArguments("FieldForEventParameter", "22").WithLocation(56, 39), Diagnostic("ID", "FieldForDelegateSubParameter").WithArguments("FieldForDelegateSubParameter", "23").WithLocation(50, 49), Diagnostic("ID", "FieldForDelegateFunctionParameter").WithArguments("FieldForDelegateFunctionParameter", "24").WithLocation(53, 53), Diagnostic("ID", "FieldForIndexerParameter").WithArguments("FieldForIndexerParameter", "25").WithLocation(83, 40), Diagnostic("ID", "C.FieldForAssembly").WithArguments("FieldForAssembly", "26").WithLocation(3, 24), Diagnostic("ID", "C.FieldForModule").WithArguments("FieldForModule", "27").WithLocation(4, 22), Diagnostic("ID", "FieldForMethodReturnType").WithArguments("FieldForMethodReturnType", "28").WithLocation(39, 95), Diagnostic("ID", "FieldForDelegateFunctionReturnType").WithArguments("FieldForDelegateFunctionReturnType", "29").WithLocation(53, 120), Diagnostic("ID", "FieldForPropertyReturnType").WithArguments("FieldForPropertyReturnType", "30").WithLocation(72, 43), Diagnostic("ID", "FieldForIndexerReturnType").WithArguments("FieldForIndexerReturnType", "31").WithLocation(83, 101)) End Sub <Fact, WorkItem(25167, "https://github.com/dotnet/roslyn/issues/25167")> Public Sub TestMethodBodyOperationAnalyzer() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Friend Class C Sub New() End Sub Sub M() End Sub End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib40AndVBRuntime(source) comp.VerifyDiagnostics() ' VB methods/constructors don't have an IMethodBodyOperation or an IConstructorBodyOperation. comp.VerifyAnalyzerDiagnostics({New MethodOrConstructorBodyOperationAnalyzer()}) End Sub <Fact, CompilerTrait(CompilerFeature.IOperation, CompilerFeature.Dataflow)> Public Sub TestGetControlFlowGraphInOperationAnalyzers() Dim source = <compilation> <file name="c.vb"> <![CDATA[ Class C Private Sub M(Optional p As Integer = 0) Dim x As Integer = 1 + 2 End Sub End Class ]]> </file> </compilation> Dim comp = CreateCompilationWithMscorlib45AndVBRuntime(source) comp.VerifyDiagnostics() ' 1. Method body flow graph ' 2. Parameter initializer flow graph Dim expectedFlowGraphs = { <![CDATA[ Block[B0] - Entry Statements (0) Next (Regular) Block[B1] Entering: {R1} .locals {R1} { Locals: [x As System.Int32] Block[B1] - Block Predecessors: [B0] Statements (1) ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x As Integer = 1 + 2') Left: ILocalReferenceOperation: x (IsDeclaration: True) (OperationKind.LocalReference, Type: System.Int32, IsImplicit) (Syntax: 'x') Right: IBinaryOperation (BinaryOperatorKind.Add, Checked) (OperationKind.Binary, Type: System.Int32, Constant: 3) (Syntax: '1 + 2') Left: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1') Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') Next (Regular) Block[B2] Leaving: {R1} } Block[B2] - Exit Predecessors: [B1] Statements (0) ]]>.Value, <![CDATA[ Block[B0] - Entry Statements (0) Next (Regular) Block[B1] Block[B1] - Block Predecessors: [B0] Statements (1) ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsImplicit) (Syntax: '= 0') Left: IParameterReferenceOperation: p (OperationKind.ParameterReference, Type: System.Int32, IsImplicit) (Syntax: '= 0') Right: ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0') Next (Regular) Block[B2] Block[B2] - Exit Predecessors: [B1] Statements (0) ]]>.Value} ' Verify analyzer diagnostics and flow graphs for different kind of operation analyzers. Dim analyzer = New OperationAnalyzer(OperationAnalyzer.ActionKind.Operation, verifyGetControlFlowGraph:=True) comp.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("ID", "0").WithArguments("Operation").WithLocation(2, 43), Diagnostic("ID", "1").WithArguments("Operation").WithLocation(3, 28), Diagnostic("ID", "2").WithArguments("Operation").WithLocation(3, 32)) verifyFlowGraphs(comp, analyzer.GetControlFlowGraphs(), expectedFlowGraphs) analyzer = New OperationAnalyzer(OperationAnalyzer.ActionKind.OperationInOperationBlockStart, verifyGetControlFlowGraph:=True) comp.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("ID", "0").WithArguments("OperationInOperationBlockStart").WithLocation(2, 43), Diagnostic("ID", "1").WithArguments("OperationInOperationBlockStart").WithLocation(3, 28), Diagnostic("ID", "2").WithArguments("OperationInOperationBlockStart").WithLocation(3, 32)) verifyFlowGraphs(comp, analyzer.GetControlFlowGraphs(), expectedFlowGraphs) analyzer = New OperationAnalyzer(OperationAnalyzer.ActionKind.OperationBlock, verifyGetControlFlowGraph:=True) comp.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("ID", "M").WithArguments("OperationBlock").WithLocation(2, 17)) verifyFlowGraphs(comp, analyzer.GetControlFlowGraphs(), expectedFlowGraphs) analyzer = New OperationAnalyzer(OperationAnalyzer.ActionKind.OperationBlockEnd, verifyGetControlFlowGraph:=True) comp.VerifyAnalyzerDiagnostics({analyzer}, Nothing, Nothing, Diagnostic("ID", "M").WithArguments("OperationBlockEnd").WithLocation(2, 17)) verifyFlowGraphs(comp, analyzer.GetControlFlowGraphs(), expectedFlowGraphs) End Sub Private Shared Sub verifyFlowGraphs(compilation As Compilation, flowGraphs As ImmutableArray(Of (Graph As ControlFlowGraph, AssociatedSymbol As ISymbol)), expectedFlowGraphs As String()) For i As Integer = 0 To expectedFlowGraphs.Length - 1 Dim expectedFlowGraph As String = expectedFlowGraphs(i) Dim actualFlowGraphAndSymbol As (Graph As ControlFlowGraph, AssociatedSymbol As ISymbol) = flowGraphs(i) ControlFlowGraphVerifier.VerifyGraph(compilation, expectedFlowGraph, actualFlowGraphAndSymbol.Graph, actualFlowGraphAndSymbol.AssociatedSymbol) Next End Sub <Fact, WorkItem(30309, "https://github.com/dotnet/roslyn/issues/30309")> Public Sub TestSymbolStartAnalyzer_MyApplication() Dim sources = <compilation> <file name="a.vb"><![CDATA[ Namespace My Friend Partial Class MyApplication End Class End Namespace ]]></file> </compilation> Dim defines = AddPredefinedPreprocessorSymbols(OutputKind.WindowsApplication) defines = defines.Add(KeyValuePair.Create("_MyType", CObj("WindowsForms"))) Dim parseOptions = New VisualBasicParseOptions(preprocessorSymbols:=defines) Dim compilationOptions = TestOptions.ReleaseExe.WithParseOptions(parseOptions) Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(sources, {SystemWindowsFormsRef}, options:=compilationOptions) compilation.VerifyDiagnostics() Dim analyzers = New DiagnosticAnalyzer() {New SymbolStartAnalyzer(topLevelAction:=False, SymbolKind.NamedType)} compilation.VerifyAnalyzerDiagnostics(analyzers, Nothing, Nothing, Diagnostic("SymbolStartRuleId").WithArguments("MyApplication", "Analyzer1").WithLocation(1, 1)) End Sub <Theory, CombinatorialData> Public Async Function TestAdditionalFileAnalyzer(registerFromInitialize As Boolean) As Task Dim tree = VisualBasicSyntaxTree.ParseText(String.Empty) Dim compilation = CreateCompilationWithMscorlib461({tree}) compilation.VerifyDiagnostics() Dim additionalFile As AdditionalText = New TestAdditionalText("Additional File Text") Dim options = New AnalyzerOptions(ImmutableArray.Create(additionalFile)) Dim diagnosticSpan = New TextSpan(2, 2) Dim analyzer = New AdditionalFileAnalyzer(registerFromInitialize, diagnosticSpan) Dim analyzers As ImmutableArray(Of DiagnosticAnalyzer) = ImmutableArray.Create(Of DiagnosticAnalyzer)(analyzer) Dim diagnostics = Await compilation.WithAnalyzers(analyzers, options).GetAnalyzerDiagnosticsAsync(CancellationToken.None) TestAdditionalFileAnalyzer_VerifyDiagnostics(diagnostics, diagnosticSpan, analyzer, additionalFile) Dim analysisResult = Await compilation.WithAnalyzers(analyzers, options).GetAnalysisResultAsync(additionalFile, CancellationToken.None) TestAdditionalFileAnalyzer_VerifyDiagnostics(analysisResult.GetAllDiagnostics(), diagnosticSpan, analyzer, additionalFile) TestAdditionalFileAnalyzer_VerifyDiagnostics(analysisResult.AdditionalFileDiagnostics(additionalFile)(analyzer), diagnosticSpan, analyzer, additionalFile) analysisResult = Await compilation.WithAnalyzers(analyzers, options).GetAnalysisResultAsync(CancellationToken.None) TestAdditionalFileAnalyzer_VerifyDiagnostics(analysisResult.GetAllDiagnostics(), diagnosticSpan, analyzer, additionalFile) TestAdditionalFileAnalyzer_VerifyDiagnostics(analysisResult.AdditionalFileDiagnostics(additionalFile)(analyzer), diagnosticSpan, analyzer, additionalFile) End Function Private Shared Sub TestAdditionalFileAnalyzer_VerifyDiagnostics(diagnostics As ImmutableArray(Of Diagnostic), expectedDiagnosticSpan As TextSpan, Analyzer As AdditionalFileAnalyzer, additionalFile As AdditionalText) Dim diagnostic = Assert.Single(diagnostics) Assert.Equal(Analyzer.Descriptor.Id, diagnostic.Id) Assert.Equal(LocationKind.ExternalFile, diagnostic.Location.Kind) Dim location = DirectCast(diagnostic.Location, ExternalFileLocation) Assert.Equal(additionalFile.Path, location.GetLineSpan().Path) Assert.Equal(expectedDiagnosticSpan, location.SourceSpan) End Sub <Fact> Public Sub TestSemanticModelProvider() Dim tree = VisualBasicSyntaxTree.ParseText(" Class C End Class") Dim compilation As Compilation = CreateCompilation({tree}) Dim semanticModelProvider = New MySemanticModelProvider() compilation = compilation.WithSemanticModelProvider(semanticModelProvider) ' Verify semantic model provider is used by Compilation.GetSemanticModel API Dim model = compilation.GetSemanticModel(tree) semanticModelProvider.VerifyCachedModel(tree, model) ' Verify semantic model provider is used by VisualBasicCompilation.GetSemanticModel API model = CType(compilation, VisualBasicCompilation).GetSemanticModel(tree, ignoreAccessibility:=False) semanticModelProvider.VerifyCachedModel(tree, model) End Sub Private NotInheritable Class MySemanticModelProvider Inherits SemanticModelProvider Private ReadOnly _cache As New ConcurrentDictionary(Of SyntaxTree, SemanticModel)() #Disable Warning RSEXPERIMENTAL001 ' Test usage of experimental API Public Overrides Function GetSemanticModel(tree As SyntaxTree, compilation As Compilation, Optional options As SemanticModelOptions = SemanticModelOptions.None) As SemanticModel Return _cache.GetOrAdd(tree, compilation.CreateSemanticModel(tree, options)) End Function Public Sub VerifyCachedModel(tree As SyntaxTree, model As SemanticModel) Assert.Same(model, _cache(tree)) End Sub End Class End Class End Namespace