/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/CodeGeneration/VisualBasicDeclarationComparer.vb
418 строк
18 KB
Cyrus Najmabadi
Move vb code
24 июл 2024, 22:45
24 июл 2024, 22:45
46c42bd
Код
Авторство
О чём код?
' 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.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Friend Class VisualBasicDeclarationComparer Implements IComparer(Of SyntaxNode) Private Shared ReadOnly s_kindPrecedenceMap As Dictionary(Of SyntaxKind, Integer) = New Dictionary(Of SyntaxKind, Integer)(SyntaxFacts.EqualityComparer) From { {SyntaxKind.FieldDeclaration, 0}, {SyntaxKind.ConstructorBlock, 1}, {SyntaxKind.SubNewStatement, 1}, {SyntaxKind.PropertyBlock, 2}, {SyntaxKind.PropertyStatement, 2}, {SyntaxKind.EventBlock, 3}, {SyntaxKind.EventStatement, 3}, {SyntaxKind.SubBlock, 4}, {SyntaxKind.SubStatement, 4}, {SyntaxKind.FunctionBlock, 5}, {SyntaxKind.FunctionStatement, 5}, {SyntaxKind.OperatorBlock, 6}, {SyntaxKind.OperatorStatement, 6}, {SyntaxKind.EnumBlock, 7}, {SyntaxKind.InterfaceBlock, 8}, {SyntaxKind.StructureBlock, 9}, {SyntaxKind.ClassBlock, 10}, {SyntaxKind.ModuleBlock, 11}, {SyntaxKind.DelegateSubStatement, 12}, {SyntaxKind.DelegateFunctionStatement, 12} } Private Shared ReadOnly s_operatorPrecedenceMap As Dictionary(Of SyntaxKind, Integer) = New Dictionary(Of SyntaxKind, Integer)(SyntaxFacts.EqualityComparer) From { {SyntaxKind.PlusToken, 0}, {SyntaxKind.MinusToken, 1}, {SyntaxKind.AsteriskToken, 3}, {SyntaxKind.SlashToken, 4}, {SyntaxKind.BackslashToken, 5}, {SyntaxKind.CaretToken, 6}, {SyntaxKind.AmpersandToken, 7}, {SyntaxKind.NotKeyword, 8}, {SyntaxKind.LikeKeyword, 9}, {SyntaxKind.ModKeyword, 10}, {SyntaxKind.AndKeyword, 11}, {SyntaxKind.OrKeyword, 12}, {SyntaxKind.XorKeyword, 13}, {SyntaxKind.LessThanLessThanToken, 14}, {SyntaxKind.GreaterThanGreaterThanToken, 15}, {SyntaxKind.EqualsToken, 16}, {SyntaxKind.LessThanGreaterThanToken, 17}, {SyntaxKind.GreaterThanToken, 18}, {SyntaxKind.LessThanToken, 19}, {SyntaxKind.GreaterThanEqualsToken, 20}, {SyntaxKind.LessThanEqualsToken, 21}, {SyntaxKind.IsTrueKeyword, 22}, {SyntaxKind.IsFalseKeyword, 23}, {SyntaxKind.CTypeKeyword, 24} } Public Shared ReadOnly WithNamesInstance As New VisualBasicDeclarationComparer(includeName:=True) Public Shared ReadOnly WithoutNamesInstance As New VisualBasicDeclarationComparer(includeName:=False) Private ReadOnly _includeName As Boolean Private Sub New(includeName As Boolean) _includeName = includeName End Sub Public Function Compare(x As SyntaxNode, y As SyntaxNode) As Integer Implements IComparer(Of SyntaxNode).Compare Dim xPrecedence As Integer Dim yPrecedence As Integer If Not s_kindPrecedenceMap.TryGetValue(x.Kind(), xPrecedence) OrElse Not s_kindPrecedenceMap.TryGetValue(y.Kind(), yPrecedence) Then ' The containing definition is malformed and contains a node kind we didn't expect. ' Ignore comparisons with those unexpected nodes and sort them to the end of the declaration. Return 1 End If If xPrecedence <> yPrecedence Then Return If(xPrecedence < yPrecedence, -1, 1) End If x = ConvertBlockToStatement(x) y = ConvertBlockToStatement(y) Select Case x.Kind Case SyntaxKind.DelegateSubStatement, SyntaxKind.DelegateFunctionStatement Return Compare(DirectCast(x, DelegateStatementSyntax), DirectCast(y, DelegateStatementSyntax)) Case SyntaxKind.FieldDeclaration Return Compare(DirectCast(x, FieldDeclarationSyntax), DirectCast(y, FieldDeclarationSyntax)) Case SyntaxKind.SubNewStatement Return Compare(DirectCast(x, SubNewStatementSyntax), DirectCast(y, SubNewStatementSyntax)) Case SyntaxKind.SubStatement, SyntaxKind.FunctionStatement Return Compare(DirectCast(x, MethodStatementSyntax), DirectCast(y, MethodStatementSyntax)) Case SyntaxKind.EventStatement Return Compare(DirectCast(x, EventStatementSyntax), DirectCast(y, EventStatementSyntax)) Case SyntaxKind.PropertyStatement Return Compare(DirectCast(x, PropertyStatementSyntax), DirectCast(y, PropertyStatementSyntax)) Case SyntaxKind.OperatorStatement Return Compare(DirectCast(x, OperatorStatementSyntax), DirectCast(y, OperatorStatementSyntax)) Case SyntaxKind.EnumStatement Return Compare(DirectCast(x, EnumStatementSyntax), DirectCast(y, EnumStatementSyntax)) Case SyntaxKind.InterfaceStatement, SyntaxKind.StructureStatement, SyntaxKind.ClassStatement, SyntaxKind.ModuleStatement Return Compare(DirectCast(x, TypeStatementSyntax), DirectCast(y, TypeStatementSyntax)) End Select throw ExceptionUtilities.UnexpectedValue(x.Kind) End Function Private Shared Function ConvertBlockToStatement(node As SyntaxNode) As SyntaxNode Select Case node.Kind Case SyntaxKind.PropertyBlock Return DirectCast(node, PropertyBlockSyntax).PropertyStatement Case SyntaxKind.EventBlock Return DirectCast(node, EventBlockSyntax).EventStatement Case SyntaxKind.ConstructorBlock, SyntaxKind.SubBlock, SyntaxKind.FunctionBlock, SyntaxKind.OperatorBlock Return DirectCast(node, MethodBlockBaseSyntax).BlockStatement Case SyntaxKind.EnumBlock Return DirectCast(node, EnumBlockSyntax).EnumStatement Case SyntaxKind.InterfaceBlock Return DirectCast(node, InterfaceBlockSyntax).BlockStatement Case SyntaxKind.StructureBlock Return DirectCast(node, StructureBlockSyntax).BlockStatement Case SyntaxKind.ClassBlock Return DirectCast(node, ClassBlockSyntax).BlockStatement Case SyntaxKind.ModuleBlock Return DirectCast(node, ModuleBlockSyntax).BlockStatement End Select Return node End Function Private Function Compare(x As DelegateStatementSyntax, y As DelegateStatementSyntax) As Integer Dim result = 0 If EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then If _includeName Then EqualIdentifierName(x.Identifier, y.Identifier, result) End If End If Return result End Function Private Function Compare(x As FieldDeclarationSyntax, y As FieldDeclarationSyntax) As Integer Dim result = 0 If EqualConstness(x.Modifiers, y.Modifiers, result) AndAlso EqualSharedness(x.Modifiers, y.Modifiers, result) AndAlso EqualReadOnlyNess(x.Modifiers, y.Modifiers, result) AndAlso EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then If _includeName Then EqualIdentifierName( x.Declarators.FirstOrDefault().Names.FirstOrDefault().Identifier, y.Declarators.FirstOrDefault().Names.FirstOrDefault().Identifier, result) End If End If Return result End Function Private Shared Function Compare(x As SubNewStatementSyntax, y As SubNewStatementSyntax) As Integer Dim result = 0 If EqualSharedness(x.Modifiers, y.Modifiers, result) AndAlso EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then EqualParameterLists(x.ParameterList, y.ParameterList, result) End If Return result End Function Private Function Compare(x As MethodStatementSyntax, y As MethodStatementSyntax) As Integer Dim result = 0 If EqualSharedness(x.Modifiers, y.Modifiers, result) AndAlso EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then If _includeName Then EqualIdentifierName(x.Identifier, y.Identifier, result) End If End If Return result End Function Private Function Compare(x As EventStatementSyntax, y As EventStatementSyntax) As Integer Dim result = 0 If EqualSharedness(x.Modifiers, y.Modifiers, result) AndAlso EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then If _includeName Then EqualIdentifierName(x.Identifier, y.Identifier, result) End If End If Return result End Function Private Function Compare(x As PropertyStatementSyntax, y As PropertyStatementSyntax) As Integer Dim result = 0 If EqualSharedness(x.Modifiers, y.Modifiers, result) AndAlso EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then If _includeName Then EqualIdentifierName(x.Identifier, y.Identifier, result) End If End If Return result End Function Private Shared Function Compare(x As OperatorStatementSyntax, y As OperatorStatementSyntax) As Integer Dim result = 0 If EqualOperatorPrecedence(x.OperatorToken, y.OperatorToken, result) Then EqualParameterLists(x.ParameterList, y.ParameterList, result) End If Return result End Function Private Function Compare(x As EnumStatementSyntax, y As EnumStatementSyntax) As Integer Dim result = 0 If EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then If _includeName Then EqualIdentifierName(x.Identifier, y.Identifier, result) End If End If Return result End Function Private Function Compare(x As TypeStatementSyntax, y As TypeStatementSyntax) As Integer Dim result = 0 If EqualSharedness(x.Modifiers, y.Modifiers, result) AndAlso EqualAccessibility(x, x.Modifiers, y, y.Modifiers, result) Then If _includeName Then EqualIdentifierName(x.Identifier, y.Identifier, result) End If End If Return result End Function Private Shared Function NeitherNull(x As Object, y As Object, ByRef comparisonResult As Integer) As Boolean If x Is Nothing AndAlso y Is Nothing Then comparisonResult = 0 Return False ElseIf x Is Nothing Then comparisonResult = -1 Return False ElseIf y Is Nothing Then comparisonResult = 1 Return False Else comparisonResult = 0 Return True End If End Function Private Shared Function ContainsToken(list As IEnumerable(Of SyntaxToken), kind As SyntaxKind) As Boolean Return list.Contains(Function(token As SyntaxToken) Return token.Kind = kind End Function) End Function Private Enum Accessibility [Public] [Protected] [ProtectedFriend] [Friend] [Private] End Enum Private Shared Function GetAccessibilityPrecedence(declaration As SyntaxNode, modifiers As IEnumerable(Of SyntaxToken)) As Integer If ContainsToken(modifiers, SyntaxKind.PublicKeyword) Then Return Accessibility.Public ElseIf ContainsToken(modifiers, SyntaxKind.ProtectedKeyword) Then If ContainsToken(modifiers, SyntaxKind.FriendKeyword) Then Return Accessibility.ProtectedFriend End If Return Accessibility.Protected ElseIf ContainsToken(modifiers, SyntaxKind.FriendKeyword) Then Return Accessibility.Friend ElseIf ContainsToken(modifiers, SyntaxKind.PrivateKeyword) Then Return Accessibility.Private End If ' Determine default accessibility Select Case declaration.Kind Case SyntaxKind.InterfaceStatement, SyntaxKind.ModuleStatement, SyntaxKind.ClassStatement, SyntaxKind.StructureStatement ' Convert type definition statements to their corresponding blocks so we can traverse up the tree declaration = declaration.Parent End Select Dim node = declaration.Parent While node IsNot Nothing Select Case node.Kind Case SyntaxKind.InterfaceBlock ' Interface members are all Public Return Accessibility.Public Case SyntaxKind.ModuleBlock, SyntaxKind.ClassBlock ' Standard module and class members default to Public unless they are variable declarations Return If(declaration.Kind = SyntaxKind.FieldDeclaration, Accessibility.Private, Accessibility.Public) Case SyntaxKind.StructureBlock ' Structure member declarations always default to Public Return Accessibility.Public End Select node = node.Parent End While ' Namespace members default to Friend Return Accessibility.Friend End Function Private Shared Function BothHaveModifier(x As SyntaxTokenList, y As SyntaxTokenList, modifierKind As SyntaxKind, ByRef comparisonResult As Integer) As Boolean Dim xHasModifier = ContainsToken(x, modifierKind) Dim yHasModifier = ContainsToken(y, modifierKind) If xHasModifier = yHasModifier Then comparisonResult = 0 Return True End If comparisonResult = If(xHasModifier, -1, 1) Return False End Function Private Shared Function EqualSharedness(x As SyntaxTokenList, y As SyntaxTokenList, ByRef comparisonResult As Integer) As Boolean Return BothHaveModifier(x, y, SyntaxKind.SharedKeyword, comparisonResult) End Function Private Shared Function EqualReadOnlyness(x As SyntaxTokenList, y As SyntaxTokenList, ByRef comparisonResult As Integer) As Boolean Return BothHaveModifier(x, y, SyntaxKind.ReadOnlyKeyword, comparisonResult) End Function Private Shared Function EqualConstness(x As SyntaxTokenList, y As SyntaxTokenList, ByRef comparisonResult As Integer) As Boolean Return BothHaveModifier(x, y, SyntaxKind.ConstKeyword, comparisonResult) End Function Private Shared Function EqualAccessibility(x As SyntaxNode, xModifiers As SyntaxTokenList, y As SyntaxNode, yModifiers As SyntaxTokenList, ByRef comparisonResult As Integer) As Boolean Dim xAccessibility = GetAccessibilityPrecedence(x, xModifiers) Dim yAccessibility = GetAccessibilityPrecedence(y, yModifiers) If xAccessibility = yAccessibility Then comparisonResult = 0 Return True End If comparisonResult = If(xAccessibility < yAccessibility, -1, 1) Return False End Function Private Shared Function EqualIdentifierName(x As SyntaxToken, y As SyntaxToken, ByRef comparisonResult As Integer) As Boolean comparisonResult = CaseInsensitiveComparison.Compare(x.ValueText, y.ValueText) Return comparisonResult = 0 End Function Private Shared Function EqualOperatorPrecedence(x As SyntaxToken, y As SyntaxToken, ByRef comparisonResult As Integer) As Boolean Dim xPrecedence = 0 Dim yPrecedence = 0 s_operatorPrecedenceMap.TryGetValue(x.Kind, xPrecedence) s_operatorPrecedenceMap.TryGetValue(y.Kind, yPrecedence) comparisonResult = If(xPrecedence = yPrecedence, 0, If(xPrecedence < yPrecedence, -1, 1)) Return comparisonResult = 0 End Function Private Shared Function EqualParameterLists(x As ParameterListSyntax, y As ParameterListSyntax, ByRef comparisonResult As Integer) As Boolean Dim result = 0 If NeitherNull(x, y, result) Then Dim xParameterCount = x.Parameters.Count Dim yParameterCount = y.Parameters.Count comparisonResult = If(xParameterCount = yParameterCount, 0, If(x.Parameters.Count < y.Parameters.Count, -1, 1)) End If Return comparisonResult = 0 End Function End Class End Namespace