165 lines
7.9 KiB
VB.net
Raw Normal View History

2021-09-20 18:20:01 +02:00
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Formatting.Rules
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Utilities
Namespace Global.dnSpy.Roslyn.VisualBasic.Internal.SmartIndent
Friend Class SpecialFormattingRule
Inherits AbstractFormattingRule
Public Sub New()
End Sub
Public Overrides Sub AddSuppressOperations(list As List(Of SuppressOperation), node As SyntaxNode, lastToken As SyntaxToken, optionSet As OptionSet, nextOperation As NextAction(Of SuppressOperation))
' don't suppress anything
End Sub
Public Overrides Function GetAdjustNewLinesOperation(previousToken As SyntaxToken, currentToken As SyntaxToken, optionSet As OptionSet, nextOperation As NextOperation(Of AdjustNewLinesOperation)) As AdjustNewLinesOperation
' unlike regular one. force position of attribute
Dim attributeNode = TryCast(previousToken.Parent, AttributeListSyntax)
If attributeNode IsNot Nothing AndAlso attributeNode.GreaterThanToken = previousToken Then
Return FormattingOperations.CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines)
End If
' no line operation. no line changes what so ever
Dim lineOperation = MyBase.GetAdjustNewLinesOperation(previousToken, currentToken, optionSet, nextOperation)
If lineOperation IsNot Nothing Then
' basically means don't ever put new line if there isn't already one, but do
' indentation.
Return FormattingOperations.CreateAdjustNewLinesOperation(line:=0, option:=AdjustNewLinesOption.PreserveLines)
End If
Return Nothing
End Function
Public Overrides Function GetAdjustSpacesOperation(previousToken As SyntaxToken, currentToken As SyntaxToken, optionSet As OptionSet, nextOperation As NextOperation(Of AdjustSpacesOperation)) As AdjustSpacesOperation
Dim spaceOperation = MyBase.GetAdjustSpacesOperation(previousToken, currentToken, optionSet, nextOperation)
' if there is force space operation, convert it to ForceSpaceIfSingleLine operation.
' (force space basically means remove all line breaks)
If spaceOperation IsNot Nothing AndAlso spaceOperation.Option = AdjustSpacesOption.ForceSpaces Then
Return FormattingOperations.CreateAdjustSpacesOperation(spaceOperation.Space, AdjustSpacesOption.ForceSpacesIfOnSingleLine)
End If
Return spaceOperation
End Function
Public Overrides Sub AddIndentBlockOperations(list As List(Of IndentBlockOperation), node As SyntaxNode, optionSet As OptionSet, nextOperation As NextAction(Of IndentBlockOperation))
nextOperation.Invoke(list)
Dim singleLineLambdaFunction = TryCast(node, SingleLineLambdaExpressionSyntax)
If singleLineLambdaFunction IsNot Nothing Then
Dim baseToken = node.GetFirstToken(includeZeroWidth:=True)
Dim endToken = node.GetLastToken()
Dim nextToken = endToken.GetNextToken(includeZeroWidth:=True)
If SyntaxFacts.AllowsTrailingImplicitLineContinuation(endToken) OrElse
SyntaxFacts.AllowsLeadingImplicitLineContinuation(nextToken) OrElse
endToken.TrailingTrivia.Any(SyntaxKind.LineContinuationTrivia) Then
Dim startToken = baseToken.GetNextToken(includeZeroWidth:=True)
list.Add(FormattingOperations.CreateRelativeIndentBlockOperation(
baseToken, startToken, endToken,
TextSpan.FromBounds(startToken.FullSpan.Start, node.FullSpan.End), indentationDelta:=1, [option]:=IndentBlockOption.RelativePosition))
End If
Return
End If
AddIndentBlockOperations(Of ParameterListSyntax)(list, node, Function(n) Not n.OpenParenToken.IsMissing AndAlso n.Parameters.Count > 0)
AddIndentBlockOperations(Of ArgumentListSyntax)(list, node, Function(n) Not n.OpenParenToken.IsMissing AndAlso n.Arguments.Count > 0 AndAlso n.Arguments.Any(Function(a) Not a.IsMissing))
AddIndentBlockOperations(Of TypeParameterListSyntax)(list, node, Function(n) Not n.OpenParenToken.IsMissing AndAlso n.Parameters.Count > 0, indentationDelta:=1)
End Sub
Private Overloads Sub AddIndentBlockOperations(Of T As SyntaxNode)(list As List(Of IndentBlockOperation), node As SyntaxNode, predicate As Func(Of T, Boolean), Optional indentationDelta As Integer = 0)
Dim parameterOrArgumentList = TryCast(node, T)
If parameterOrArgumentList Is Nothing Then
Return
End If
If Not predicate(parameterOrArgumentList) Then
Return
End If
AddIndentBlockOperations(list, parameterOrArgumentList, indentationDelta)
End Sub
Private Overloads Sub AddIndentBlockOperations(list As List(Of IndentBlockOperation), parameterOrArgumentList As SyntaxNode, indentationDelta As Integer)
Dim openBrace = parameterOrArgumentList.GetFirstToken(includeZeroWidth:=True)
Dim closeBrace = parameterOrArgumentList.GetLastToken(includeZeroWidth:=True)
' first token of first argument (first token of the node should be "open brace")
Dim baseToken = openBrace.GetNextToken(includeZeroWidth:=True)
' indent block start token
Dim startToken = baseToken.GetNextToken(includeZeroWidth:=True)
' last token of last argument (last token of the node should be "close brace")
Dim endToken = closeBrace.GetPreviousToken(includeZeroWidth:=True)
list.Add(FormattingOperations.CreateRelativeIndentBlockOperation(
baseToken, startToken, endToken, TextSpan.FromBounds(baseToken.Span.End, closeBrace.Span.End), indentationDelta, IndentBlockOption.RelativePosition))
End Sub
Public Overrides Sub AddAlignTokensOperations(operations As List(Of AlignTokensOperation), node As SyntaxNode, optionSet As OptionSet, nextAction As NextAction(Of AlignTokensOperation))
MyBase.AddAlignTokensOperations(operations, node, optionSet, nextAction)
' Smart token formatting off: No token alignment
If optionSet.GetOption(FormattingOptions.SmartIndent, LanguageNames.VisualBasic) <> FormattingOptions.IndentStyle.Smart Then
Return
End If
AddAlignTokensOperations(Of ParameterListSyntax)(operations, node, Function(n) n.OpenParenToken)
AddAlignTokensOperations(Of TypeParameterListSyntax)(operations, node, Function(n) n.OpenParenToken)
AddAlignTokensOperations(Of ArrayRankSpecifierSyntax)(operations, node, Function(n) n.OpenParenToken)
AddCaseClauseAlignTokensOperations(operations, node)
End Sub
Private Sub AddCaseClauseAlignTokensOperations(operations As List(Of AlignTokensOperation), node As SyntaxNode)
Dim caseStatement = TryCast(node, CaseStatementSyntax)
If caseStatement Is Nothing OrElse caseStatement.Cases.Count = 0 Then
Return
End If
Dim cases = caseStatement.Cases.OfType(Of SimpleCaseClauseSyntax).ToList()
If cases.Count < 2 Then
Return
End If
operations.Add(FormattingOperations.CreateAlignTokensOperation(
cases(0).GetFirstToken(includeZeroWidth:=True),
cases.Skip(1).Select(Function(n) n.GetFirstToken(includeZeroWidth:=True)),
AlignTokensOption.AlignIndentationOfTokensToBaseToken))
End Sub
Private Overloads Sub AddAlignTokensOperations(Of T As SyntaxNode)(operations As List(Of AlignTokensOperation), node As SyntaxNode, baseTokenGetter As Func(Of T, SyntaxToken))
Dim parameterList = TryCast(node, T)
If parameterList Is Nothing Then
Return
End If
Dim baseToken = baseTokenGetter(parameterList)
If baseToken.IsMissing Then
Return
End If
AddAlignTokensOperations(operations, baseToken)
End Sub
Private Overloads Sub AddAlignTokensOperations(operations As List(Of AlignTokensOperation), baseToken As SyntaxToken)
operations.Add(FormattingOperations.CreateAlignTokensOperation(
baseToken,
New SyntaxToken() {baseToken.GetNextToken(includeZeroWidth:=True)},
AlignTokensOption.AlignIndentationOfTokensToBaseToken))
End Sub
End Class
End Namespace