File: BasicSymbolDeclaredEventMustBeGeneratedForSourceSymbols.vb
Web Access
Project: src\src\roslyn\src\RoslynAnalyzers\Roslyn.Diagnostics.Analyzers\VisualBasic\Roslyn.Diagnostics.VisualBasic.Analyzers.vbproj (Roslyn.Diagnostics.VisualBasic.Analyzers)
' 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.Immutable
Imports Analyzer.Utilities.Extensions
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Diagnostics.Analyzers

Namespace Roslyn.Diagnostics.VisualBasic.Analyzers
    <DiagnosticAnalyzer(LanguageNames.VisualBasic)>
    Public Class BasicSymbolDeclaredEventAnalyzer
        Inherits SymbolDeclaredEventAnalyzer(Of SyntaxKind)

        Private Const SourceModuleTypeFullName As String = "Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceModuleSymbol"

        Protected Overrides Function GetCompilationAnalyzer(compilation As Compilation, symbolType As INamedTypeSymbol) As CompilationAnalyzer
            Dim compilationType = compilation.GetOrCreateTypeByMetadataName(GetType(VisualBasicCompilation).FullName)
            If compilationType Is Nothing Then
                Return Nothing
            End If

            Dim sourceModuleType = compilation.GetOrCreateTypeByMetadataName(SourceModuleTypeFullName)
            If sourceModuleType Is Nothing Then
                Return Nothing
            End If

            Return New BasicCompilationAnalyzer(symbolType, compilationType, sourceModuleType)
        End Function

        Protected Overrides ReadOnly Property InvocationExpressionSyntaxKind As SyntaxKind
            Get
                Return SyntaxKind.InvocationExpression
            End Get
        End Property

        Private NotInheritable Class BasicCompilationAnalyzer
            Inherits CompilationAnalyzer

            Private ReadOnly _sourceModuleType As INamedTypeSymbol

            Private Shared ReadOnly s_symbolTypesWithExpectedSymbolDeclaredEvent As ImmutableHashSet(Of String) =
                ImmutableHashSet.Create("SourceNamespaceSymbol", "SourceNamedTypeSymbol", "SourceEventSymbol", "SourceFieldSymbol", "SourceMethodSymbol", "SourcePropertySymbol")
            Private Const s_atomicSetFlagAndRaiseSymbolDeclaredEventName As String = "AtomicSetFlagAndRaiseSymbolDeclaredEvent"

            Public Sub New(symbolType As INamedTypeSymbol, compilationType As INamedTypeSymbol, sourceModuleSymbol As INamedTypeSymbol)
                MyBase.New(symbolType, compilationType)
                Me._sourceModuleType = sourceModuleSymbol
            End Sub

            Protected Overrides ReadOnly Property SymbolTypesWithExpectedSymbolDeclaredEvent As ImmutableHashSet(Of String)
                Get
                    Return s_symbolTypesWithExpectedSymbolDeclaredEvent
                End Get
            End Property

            Protected Overrides Function GetFirstArgumentOfInvocation(invocation As SyntaxNode) As SyntaxNode
                Dim invocationExpression = DirectCast(invocation, InvocationExpressionSyntax)
                If invocationExpression.ArgumentList IsNot Nothing Then
                    Dim argument = invocationExpression.ArgumentList.Arguments.FirstOrDefault()
                    If argument IsNot Nothing Then
                        Return argument.GetExpression
                    End If
                End If

                Return Nothing
            End Function

            Friend Overrides Sub AnalyzeMethodInvocation(invocationSymbol As IMethodSymbol, context As SyntaxNodeAnalysisContext)
                If invocationSymbol.Name.Equals(s_atomicSetFlagAndRaiseSymbolDeclaredEventName, StringComparison.OrdinalIgnoreCase) AndAlso
                    _sourceModuleType.Equals(invocationSymbol.ContainingType) Then

                    Dim invocationExp = DirectCast(context.Node, InvocationExpressionSyntax)
                    If invocationExp.ArgumentList IsNot Nothing Then
                        For Each argument In invocationExp.ArgumentList.Arguments
                            If AnalyzeSymbolDeclaredEventInvocation(argument.GetExpression, context) Then
                                Exit For
                            End If
                        Next
                    End If
                End If

                MyBase.AnalyzeMethodInvocation(invocationSymbol, context)
            End Sub
        End Class
    End Class
End Namespace