/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Extensions/DirectiveSyntaxExtensions.vb
80 строк
4 KB
Cyrus Najmabadi
Avoid unnecessary tree walk when hitting non-relevant directives
26 май 2024, 09:22
26 май 2024, 09:22
7d61a64
Код
Авторство
О чём код?
' 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 System.Runtime.CompilerServices Imports System.Threading Imports Microsoft.CodeAnalysis.VisualBasic.LanguageService Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Friend Module DirectiveSyntaxExtensions Private ReadOnly s_rootToDirectiveInfo As New ConditionalWeakTable(Of SyntaxNode, DirectiveInfo(Of DirectiveTriviaSyntax))() Private Function GetDirectiveInfo(node As SyntaxNode, cancellationToken As CancellationToken) As DirectiveInfo(Of DirectiveTriviaSyntax) Return s_rootToDirectiveInfo.GetValue(node.GetAbsoluteRoot(), Function(r) GetDirectiveInfoForRoot(r, cancellationToken)) End Function Private Function GetDirectiveInfoForRoot(root As SyntaxNode, cancellationToken As CancellationToken) As DirectiveInfo(Of DirectiveTriviaSyntax) Return [Shared].Extensions.SyntaxNodeExtensions.GetDirectiveInfoForRoot(Of DirectiveTriviaSyntax)( root, VisualBasicSyntaxKinds.Instance, cancellationToken) End Function <Extension()> Private Function GetAbsoluteRoot(node As SyntaxNode) As SyntaxNode While node IsNot Nothing AndAlso (node.Parent IsNot Nothing OrElse TypeOf node Is StructuredTriviaSyntax) If node.Parent IsNot Nothing Then node = node.Parent Else node = node.ParentTrivia.Token.Parent End If End While Return node End Function <Extension()> Public Function GetStartDirectives(syntaxTree As SyntaxTree, cancellationToken As CancellationToken) As IEnumerable(Of DirectiveTriviaSyntax) Return GetDirectiveInfo(syntaxTree.GetRoot(cancellationToken), cancellationToken).DirectiveMap.Keys.Where( Function(d) d.Kind = SyntaxKind.RegionDirectiveTrivia OrElse d.Kind = SyntaxKind.IfDirectiveTrivia) End Function ''' <summary> ''' Given a starting or ending directive, return the matching directive, if it exists. For directives that live ''' the "middle" of a start/end pair, such as #ElseIf or #Else, this method will throw. ''' </summary> <Extension()> Public Function GetMatchingStartOrEndDirective(directive As DirectiveTriviaSyntax, cancellationToken As CancellationToken) As DirectiveTriviaSyntax If directive Is Nothing Then Throw New ArgumentNullException(NameOf(directive)) End If If directive.Kind = SyntaxKind.ElseIfDirectiveTrivia OrElse directive.Kind = SyntaxKind.ElseDirectiveTrivia Then Throw New ArgumentException("directive cannot be a ElseIfDirective or ElseDirective.") End If Dim result As DirectiveTriviaSyntax = Nothing GetDirectiveInfo(directive, cancellationToken).DirectiveMap.TryGetValue(directive, result) Return result End Function ''' <summary> ''' Given a conditional directive (#If, #ElseIf, #Else, or #End If), returns a IEnumerable of all directives in ''' the set. ''' </summary> <Extension> Public Function GetMatchingConditionalDirectives(directive As DirectiveTriviaSyntax, cancellationToken As CancellationToken) As ImmutableArray(Of DirectiveTriviaSyntax) If directive Is Nothing Then Throw New ArgumentNullException(NameOf(directive)) End If Dim result As ImmutableArray(Of DirectiveTriviaSyntax) = Nothing Return If(GetDirectiveInfo(directive, cancellationToken).ConditionalMap.TryGetValue(directive, result), result, ImmutableArray(Of DirectiveTriviaSyntax).Empty) End Function End Module End Namespace