/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/VisualBasic/Formatting/DefaultOperationProvider.vb
220 строк
11 KB
Cyrus Najmabadi
move more
20 июн 2025, 21:59
20 июн 2025, 21:59
aa96d9d
Код
Авторство
О чём код?
' 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 Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Formatting.Rules Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Utilities Namespace Microsoft.CodeAnalysis.VisualBasic.Formatting ' the default provider that will be called by the engine at the end of provider's chain. ' there is no way for a user to be remove this provider. ' ' to reduce number of unnecessary heap allocations, most of them just return null. Friend NotInheritable Class DefaultOperationProvider Inherits CompatAbstractFormattingRule Public Shared ReadOnly Instance As New DefaultOperationProvider() Private ReadOnly _options As SyntaxFormattingOptions Private Sub New() MyClass.New(VisualBasicSyntaxFormattingOptions.Default) End Sub Private Sub New(options As SyntaxFormattingOptions) _options = options End Sub Public Overrides Function WithOptions(options As SyntaxFormattingOptions) As AbstractFormattingRule If _options.SeparateImportDirectiveGroups = options.SeparateImportDirectiveGroups Then Return Me End If Return New DefaultOperationProvider(options) End Function Public Overrides Sub AddSuppressOperationsSlow(operations As ArrayBuilder(Of SuppressOperation), node As SyntaxNode, ByRef nextAction As NextSuppressOperationAction) End Sub Public Overrides Sub AddAnchorIndentationOperationsSlow(operations As List(Of AnchorIndentationOperation), node As SyntaxNode, ByRef nextAction As NextAnchorIndentationOperationAction) End Sub Public Overrides Sub AddIndentBlockOperationsSlow(operations As List(Of IndentBlockOperation), node As SyntaxNode, ByRef nextAction As NextIndentBlockOperationAction) End Sub Public Overrides Sub AddAlignTokensOperationsSlow(operations As List(Of AlignTokensOperation), node As SyntaxNode, ByRef nextAction As NextAlignTokensOperationAction) End Sub <PerformanceSensitive("https://github.com/dotnet/roslyn/issues/30819", AllowCaptures:=False, AllowImplicitBoxing:=False)> Public Overrides Function GetAdjustNewLinesOperationSlow( ByRef previousToken As SyntaxToken, ByRef currentToken As SyntaxToken, ByRef nextOperation As NextGetAdjustNewLinesOperation) As AdjustNewLinesOperation If previousToken.Parent Is Nothing Then Return Nothing End If Dim combinedTrivia = (previousToken.TrailingTrivia, currentToken.LeadingTrivia) Dim lastTrivia = LastOrDefaultTrivia( combinedTrivia, Function(trivia As SyntaxTrivia) ColonOrLineContinuationTrivia(trivia)) If lastTrivia.RawKind = SyntaxKind.ColonTrivia Then Return FormattingOperations.CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines) ElseIf lastTrivia.RawKind = SyntaxKind.LineContinuationTrivia AndAlso previousToken.Parent.GetAncestorsOrThis(Of SyntaxNode)().Any(Function(node As SyntaxNode) IsSingleLineIfOrElseClauseSyntax(node)) Then Return Nothing End If ' return line break operation after statement terminator token so that we can enforce ' indentation for the line Dim previousStatement As StatementSyntax = Nothing If previousToken.IsLastTokenOfStatement(statement:=previousStatement) AndAlso ContainEndOfLine(previousToken, currentToken) AndAlso currentToken.Kind <> SyntaxKind.EmptyToken Then Return AdjustNewLinesBetweenStatements(previousStatement, currentToken) End If If previousToken.Kind = SyntaxKind.GreaterThanToken AndAlso previousToken.Parent IsNot Nothing AndAlso TypeOf previousToken.Parent Is AttributeListSyntax Then ' This AttributeList is the last applied attribute ' If this AttributeList belongs to a parameter then apply no line operation If previousToken.Parent.Parent IsNot Nothing AndAlso TypeOf previousToken.Parent.Parent Is ParameterSyntax Then Return Nothing End If Return FormattingOperations.CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines) End If If currentToken.Kind = SyntaxKind.LessThanToken AndAlso currentToken.Parent IsNot Nothing AndAlso TypeOf currentToken.Parent Is AttributeListSyntax Then ' The case of the previousToken belonging to another AttributeList is handled in the previous condition If (previousToken.Kind = SyntaxKind.CommaToken OrElse previousToken.Kind = SyntaxKind.OpenParenToken) AndAlso currentToken.Parent.Parent IsNot Nothing AndAlso TypeOf currentToken.Parent.Parent Is ParameterSyntax Then Return Nothing End If Return FormattingOperations.CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines) End If ' return line break operation after xml tag token so that we can enforce indentation for the xml tag ' the very first xml literal tag case If IsFirstXmlTag(currentToken) Then Return Nothing End If Dim xmlDeclaration = TryCast(previousToken.Parent, XmlDeclarationSyntax) If xmlDeclaration IsNot Nothing AndAlso xmlDeclaration.GetLastToken(includeZeroWidth:=True) = previousToken Then Return FormattingOperations.CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines) End If If TypeOf previousToken.Parent Is XmlNodeSyntax OrElse TypeOf currentToken.Parent Is XmlNodeSyntax Then Return FormattingOperations.CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines) End If Return Nothing End Function Private Function AdjustNewLinesBetweenStatements( previousStatement As StatementSyntax, currentToken As SyntaxToken) As AdjustNewLinesOperation ' if the user is separating import-groups, And we're between two imports, and these ' imports *should* be separated, then do so (if the imports were already properly ' sorted). If currentToken.Kind() = SyntaxKind.ImportsKeyword AndAlso TypeOf currentToken.Parent Is ImportsStatementSyntax AndAlso TypeOf previousStatement Is ImportsStatementSyntax Then Dim previousImports = DirectCast(previousStatement, ImportsStatementSyntax) Dim currentImports = DirectCast(currentToken.Parent, ImportsStatementSyntax) If _options.SeparateImportDirectiveGroups AndAlso ImportsOrganizer.NeedsGrouping(previousImports, currentImports) Then Dim [imports] = DirectCast(previousImports.Parent, CompilationUnitSyntax).Imports If [imports].IsSorted(ImportsStatementComparer.SystemFirstInstance) OrElse [imports].IsSorted(ImportsStatementComparer.NormalInstance) Then ' Force at least one blank line here. Return FormattingOperations.CreateAdjustNewLinesOperation(2, AdjustNewLinesOption.PreserveLines) End If End If End If ' For any other two statements we will normally ensure at least one new-line between ' them. Return FormattingOperations.CreateAdjustNewLinesOperation(1, AdjustNewLinesOption.PreserveLines) End Function Private Shared Function IsSingleLineIfOrElseClauseSyntax(node As SyntaxNode) As Boolean Return TypeOf node Is SingleLineIfStatementSyntax OrElse TypeOf node Is SingleLineElseClauseSyntax End Function Private Shared Function ColonOrLineContinuationTrivia(trivia As SyntaxTrivia) As Boolean Return trivia.RawKind = SyntaxKind.ColonTrivia OrElse trivia.RawKind = SyntaxKind.LineContinuationTrivia End Function <PerformanceSensitive("https://github.com/dotnet/roslyn/issues/30819", AllowCaptures:=False, AllowImplicitBoxing:=False)> Private Shared Function LastOrDefaultTrivia(triviaListPair As (SyntaxTriviaList, SyntaxTriviaList), predicate As Func(Of SyntaxTrivia, Boolean)) As SyntaxTrivia For Each trivia In triviaListPair.Item2.Reverse() If predicate(trivia) Then Return trivia End If Next For Each trivia In triviaListPair.Item1.Reverse() If predicate(trivia) Then Return trivia End If Next Return Nothing End Function Private Shared Function ContainEndOfLine(previousToken As SyntaxToken, nextToken As SyntaxToken) As Boolean Return previousToken.TrailingTrivia.Any(SyntaxKind.EndOfLineTrivia) OrElse nextToken.LeadingTrivia.Any(SyntaxKind.EndOfLineTrivia) End Function Private Shared Function IsFirstXmlTag(currentToken As SyntaxToken) As Boolean Dim xmlDeclaration = TryCast(currentToken.Parent, XmlDeclarationSyntax) If xmlDeclaration IsNot Nothing AndAlso xmlDeclaration.LessThanQuestionToken = currentToken AndAlso TypeOf xmlDeclaration.Parent Is XmlDocumentSyntax AndAlso TypeOf xmlDeclaration.Parent.Parent IsNot XmlNodeSyntax Then Return True End If Dim startTag = TryCast(currentToken.Parent, XmlElementStartTagSyntax) If startTag IsNot Nothing AndAlso startTag.LessThanToken = currentToken AndAlso TypeOf startTag.Parent Is XmlElementSyntax AndAlso TypeOf startTag.Parent.Parent IsNot XmlNodeSyntax Then Return True End If Dim emptyTag = TryCast(currentToken.Parent, XmlEmptyElementSyntax) If emptyTag IsNot Nothing AndAlso emptyTag.LessThanToken = currentToken AndAlso TypeOf emptyTag.Parent IsNot XmlNodeSyntax Then Return True End If Return False End Function ' return 1 space for every token pairs as a default operation Public Overrides Function GetAdjustSpacesOperationSlow(ByRef previousToken As SyntaxToken, ByRef currentToken As SyntaxToken, ByRef nextOperation As NextGetAdjustSpacesOperation) As AdjustSpacesOperation If previousToken.Kind = SyntaxKind.ColonToken AndAlso TypeOf previousToken.Parent Is LabelStatementSyntax AndAlso currentToken.Kind <> SyntaxKind.EndOfFileToken Then Return FormattingOperations.CreateAdjustSpacesOperation(1, AdjustSpacesOption.DynamicSpaceToIndentationIfOnSingleLine) End If Dim space As Integer = If(currentToken.Kind = SyntaxKind.EndOfFileToken, 0, 1) Return FormattingOperations.CreateAdjustSpacesOperation(space, AdjustSpacesOption.DefaultSpacesIfOnSingleLine) End Function End Class End Namespace