/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Features/VisualBasic/Portable/CodeFixes/MoveToTopOfFile/MoveToTopOfFileCodeFixProvider.vb
202 строки
10 KB
Tomáš Matoušek
Move SpecializedCollections to Microsoft.CodeAnalysis.Collections namespace (#78466)
15 май 2025, 00:23
Не верифицирован
15 май 2025, 00:23
4358d12
Код
Авторство
О чём код?
' 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.Composition Imports System.Diagnostics.CodeAnalysis Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CodeFixes Imports Microsoft.CodeAnalysis.Collections Imports Microsoft.CodeAnalysis.VisualBasic.CodeActions Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.MoveToTopOfFile <ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.MoveToTopOfFile), [Shared]> <ExtensionOrder(After:=PredefinedCodeFixProviderNames.ImplementInterface)> Partial Friend Class MoveToTopOfFileCodeFixProvider Inherits CodeFixProvider Friend Const BC30465 As String = "BC30465" ' 'Imports' statements must precede any declarations. Friend Const BC30637 As String = "BC30637" ' Assembly or Module attribute statements must precede any declarations in a file. Friend Const BC30627 As String = "BC30627" ' 'Option' statements must precede any declarations or 'Imports' statements. <ImportingConstructor> <SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification:="Used in test code: https://github.com/dotnet/roslyn/issues/42814")> Public Sub New() End Sub Public NotOverridable Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String) Get Return ImmutableArray.Create(BC30465, BC30637, BC30627) End Get End Property Public Overrides Function GetFixAllProvider() As FixAllProvider ' Fix All is not supported for this code fix ' https://github.com/dotnet/roslyn/issues/34471 Return Nothing End Function Public NotOverridable Overrides Async Function RegisterCodeFixesAsync(context As CodeFixContext) As Task Dim document = context.Document Dim span = context.Span Dim cancellationToken = context.CancellationToken Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) Dim token = root.FindToken(span.Start) If Not token.Span.IntersectsWith(span) Then Return End If Dim node = token _ .GetAncestors(Of DeclarationStatementSyntax) _ .FirstOrDefault(Function(c) c.Span.IntersectsWith(span)) If node Is Nothing Then Return End If Dim compilationUnit = CType(root, CompilationUnitSyntax) Dim result = SpecializedCollections.EmptyEnumerable(Of CodeAction)() If node.Kind = SyntaxKind.ImportsStatement Then Dim importsStatement = DirectCast(node, ImportsStatementSyntax) If Not compilationUnit.Imports.Contains(importsStatement) Then If DeclarationsExistAfterImports(node, compilationUnit) OrElse compilationUnit.Attributes.Any(Function(a) a.SpanStart < node.SpanStart) Then result = CreateActionForImports(document, importsStatement, compilationUnit, cancellationToken) End If End If End If If node.Kind = SyntaxKind.OptionStatement Then Dim optionStatement = DirectCast(node, OptionStatementSyntax) If Not compilationUnit.Options.Contains(optionStatement) Then result = CreateActionForOptions(document, optionStatement, compilationUnit, cancellationToken) End If End If If node.Kind = SyntaxKind.AttributesStatement Then Dim attributesStatement = DirectCast(node, AttributesStatementSyntax) If Not compilationUnit.Attributes.Contains(attributesStatement) Then result = CreateActionForAttribute(document, attributesStatement, compilationUnit, cancellationToken) End If End If If result IsNot Nothing Then context.RegisterFixes(result, context.Diagnostics) End If End Function Private Shared Function DeclarationsExistAfterImports(node As SyntaxNode, root As CompilationUnitSyntax) As Boolean Return root.Members.Any( Function(m) m IsNot node AndAlso Not m.IsKind(SyntaxKind.OptionStatement, SyntaxKind.AttributesStatement) AndAlso node.Span.End > m.SpanStart) End Function Private Shared Function CreateActionForImports(document As Document, node As ImportsStatementSyntax, root As CompilationUnitSyntax, cancellationToken As CancellationToken) As IEnumerable(Of CodeAction) Dim destinationLine As Integer = 0 If root.Imports.Any() Then destinationLine = FindLastContiguousStatement(root.Imports, root.GetLeadingBannerAndPreprocessorDirectives()) ElseIf root.Options.Any() Then destinationLine = root.Options.Last().GetLocation().GetLineSpan().EndLinePosition.Line + 1 End If If DestinationPositionIsHidden(root, destinationLine, cancellationToken) Then Return Nothing End If Return { New MoveToLineCodeAction(document, node.ImportsKeyword, destinationLine, MoveStatement("Imports", destinationLine)), New RemoveStatementCodeAction(document, node, DeleteStatement("Imports")) } End Function Private Shared Function CreateActionForOptions(document As Document, node As OptionStatementSyntax, root As CompilationUnitSyntax, cancellationToken As CancellationToken) As IEnumerable(Of CodeAction) Dim destinationLine = FindLastContiguousStatement(root.Options, root.GetLeadingBannerAndPreprocessorDirectives()) If DestinationPositionIsHidden(root, destinationLine, cancellationToken) Then Return Nothing End If Return { New MoveToLineCodeAction(document, node.OptionKeyword, destinationLine, MoveStatement("Option", destinationLine)), New RemoveStatementCodeAction(document, node, DeleteStatement("Option")) } End Function Private Shared Function CreateActionForAttribute(document As Document, node As AttributesStatementSyntax, root As CompilationUnitSyntax, cancellationToken As CancellationToken) As IEnumerable(Of CodeAction) Dim destinationLine As Integer = 0 If root.Attributes.Any() Then destinationLine = FindLastContiguousStatement(root.Attributes, root.GetLeadingBannerAndPreprocessorDirectives()) ElseIf root.Imports.Any() Then destinationLine = root.Imports.Last().GetLocation().GetLineSpan().EndLinePosition.Line + 1 ElseIf root.Options.Any() Then destinationLine = root.Options.Last().GetLocation().GetLineSpan().EndLinePosition.Line + 1 End If If DestinationPositionIsHidden(root, destinationLine, cancellationToken) Then Return Nothing End If Return { New MoveToLineCodeAction(document, node.GetFirstToken(), destinationLine, MoveStatement("Attribute", destinationLine)), New RemoveStatementCodeAction(document, node, DeleteStatement("Attribute")) } End Function Private Shared Function FindLastContiguousStatement(nodes As IEnumerable(Of SyntaxNode), trivia As IEnumerable(Of SyntaxTrivia)) As Integer If Not nodes.Any() Then Dim lastBannerText = trivia.LastOrDefault(Function(t) t.IsKind(SyntaxKind.CommentTrivia)) If lastBannerText = Nothing Then Return 0 Else Return lastBannerText.GetLocation().GetLineSpan().StartLinePosition.Line + 1 End If End If ' Advance through the list of nodes until we find one that doesn't start on the ' line immediately following the one before it. Dim expectedLine = nodes.First().GetLocation().GetLineSpan().StartLinePosition.Line For Each node In nodes Dim actualLine = node.GetLocation().GetLineSpan().StartLinePosition.Line If actualLine <> expectedLine Then Exit For End If expectedLine += 1 Next Return expectedLine End Function Private Shared Function MoveStatement(kind As String, line As Integer) As String Return String.Format(VBFeaturesResources.Move_the_0_statement_to_line_1, kind, line + 1) End Function Private Shared Function DeleteStatement(kind As String) As String Return String.Format(VBFeaturesResources.Delete_the_0_statement2, kind) End Function Private Shared Function DestinationPositionIsHidden(root As CompilationUnitSyntax, destinationLine As Integer, cancellationToken As CancellationToken) As Boolean Dim text = root.GetText() Dim position = text.Lines(destinationLine).Start Return root.SyntaxTree.IsHiddenPosition(destinationLine, cancellationToken) End Function End Class End Namespace