|
' 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 Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
Friend Class VisualBasicWarningStateMap
Inherits AbstractWarningStateMap(Of ReportDiagnostic)
Public Sub New(tree As SyntaxTree)
MyBase.New(tree)
End Sub
Protected Overrides Function CreateWarningStateMapEntries(syntaxTree As SyntaxTree) As WarningStateMapEntry()
' Accumulate all warning directives in source code order.
Dim directives = ArrayBuilder(Of DirectiveTriviaSyntax).GetInstance()
GetAllWarningDirectives(syntaxTree, directives)
' Create the warning state map.
Return CreateWarningStateEntries(directives.ToImmutableAndFree())
End Function
' Add all warning directives to the list in source code order.
Private Shared Sub GetAllWarningDirectives(syntaxTree As SyntaxTree, directiveList As ArrayBuilder(Of DirectiveTriviaSyntax))
For Each d As DirectiveTriviaSyntax In syntaxTree.GetRoot().GetDirectives()
If d.IsKind(SyntaxKind.EnableWarningDirectiveTrivia) Then
Dim w = DirectCast(d, EnableWarningDirectiveTriviaSyntax)
If (Not w.EnableKeyword.IsMissing) AndAlso (Not w.EnableKeyword.ContainsDiagnostics) AndAlso
(Not w.WarningKeyword.IsMissing) AndAlso (Not w.WarningKeyword.ContainsDiagnostics) Then
directiveList.Add(w)
End If
ElseIf d.IsKind(SyntaxKind.DisableWarningDirectiveTrivia) Then
Dim w = DirectCast(d, DisableWarningDirectiveTriviaSyntax)
If (Not w.DisableKeyword.IsMissing) AndAlso (Not w.DisableKeyword.ContainsDiagnostics) AndAlso
(Not w.WarningKeyword.IsMissing) AndAlso (Not w.WarningKeyword.ContainsDiagnostics) Then
directiveList.Add(w)
End If
End If
Next
End Sub
' Given the ordered list of all warning directives in the syntax tree, return a list of entries
' each of which captures a position in the source and the set of warnings that are disabled at this position.
Private Shared Function CreateWarningStateEntries(directiveList As ImmutableArray(Of DirectiveTriviaSyntax)) As WarningStateMapEntry()
Dim entries = New WarningStateMapEntry(directiveList.Length) {}
Dim index = 0
entries(index) = New WarningStateMapEntry(0, ReportDiagnostic.Default, Nothing)
' Captures the general reporting state.
Dim accumulatedGeneralWarningState = ReportDiagnostic.Default
' Captures reporting state for specific warnings. Diagnostic ids must be processed in case-insensitive fashion in VB.
Dim accumulatedSpecificWarningState = ImmutableDictionary.Create(Of String, ReportDiagnostic)(CaseInsensitiveComparison.Comparer)
While (index < directiveList.Length)
Dim currentDirective = directiveList(index)
Dim reportingState As ReportDiagnostic
Dim codes As SeparatedSyntaxList(Of IdentifierNameSyntax)
' Compute the reporting state.
If currentDirective.IsKind(SyntaxKind.EnableWarningDirectiveTrivia) Then
reportingState = ReportDiagnostic.Default
codes = DirectCast(currentDirective, EnableWarningDirectiveTriviaSyntax).ErrorCodes
ElseIf currentDirective.IsKind(SyntaxKind.DisableWarningDirectiveTrivia) Then
reportingState = ReportDiagnostic.Suppress
codes = DirectCast(currentDirective, DisableWarningDirectiveTriviaSyntax).ErrorCodes
End If
' Check if this directive impacts the general reporting state. (Is this "#Disable Warning" / "#Enable Warning" with no ids specified?)
If codes.Count = 0 Then
' Update the general reporting state and reset the specific one.
accumulatedGeneralWarningState = reportingState
' Diagnostic ids must be processed in case-insensitive fashion in VB.
accumulatedSpecificWarningState = ImmutableDictionary.Create(Of String, ReportDiagnostic)(CaseInsensitiveComparison.Comparer)
Else
For i As Integer = 0 To codes.Count - 1
Dim currentCode = codes(i)
If currentCode.IsMissing OrElse currentCode.ContainsDiagnostics Then
Continue For
End If
' Update the specific reporting state for the current warning.
accumulatedSpecificWarningState = accumulatedSpecificWarningState.SetItem(currentCode.Identifier.ValueText, reportingState)
Next
End If
index += 1
entries(index) = New WarningStateMapEntry(currentDirective.GetLocation().SourceSpan.End, accumulatedGeneralWarningState, accumulatedSpecificWarningState)
End While
#If DEBUG Then
' Make sure the entries array is correctly sorted.
For i As Integer = 0 To entries.Length - 2
Debug.Assert(entries(i).CompareTo(entries(i + 1)) < 0)
Next
#End If
Return entries
End Function
End Class
End Namespace
|