/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/CompilationUnitSyntaxExtensions.vb
132 строки
7 KB
Cyrus Najmabadi
Support adding package and reference assemblies from an import
08 дек 2024, 22:52
08 дек 2024, 22:52
e4bac08
Код
Авторство
О чём код?
' 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.Runtime.CompilerServices Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.AddImport Imports Microsoft.CodeAnalysis.LanguageService Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.LanguageService Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Utilities Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Friend Module CompilationUnitSyntaxExtensions <Extension> Public Function CanAddImportsStatements( contextNode As SyntaxNode, allowInHiddenRegions As Boolean, cancellationToken As CancellationToken) As Boolean If allowInHiddenRegions Then Return True End If Dim root = contextNode.GetAncestorOrThis(Of CompilationUnitSyntax)() If root.Imports.Count > 0 Then Dim start = root.Imports.First.SpanStart Dim [end] = root.Imports.Last.Span.End Return Not contextNode.SyntaxTree.OverlapsHiddenPosition(TextSpan.FromBounds(start, [end]), cancellationToken) Else Dim start = 0 Dim [end] = If(root.Members.Count > 0, root.Members.First.GetFirstToken().Span.End, root.Span.End) Return Not contextNode.SyntaxTree.OverlapsHiddenPosition(TextSpan.FromBounds(start, [end]), cancellationToken) End If End Function <Extension()> Public Function AddImportsStatement(root As CompilationUnitSyntax, importStatement As ImportsStatementSyntax, placeSystemNamespaceFirst As Boolean, ParamArray annotations As SyntaxAnnotation()) As CompilationUnitSyntax Return root.AddImportsStatements({importStatement}, placeSystemNamespaceFirst, annotations) End Function <Extension()> Public Function AddImportsStatements(root As CompilationUnitSyntax, importsStatements As IList(Of ImportsStatementSyntax), placeSystemNamespaceFirst As Boolean, ParamArray annotations As SyntaxAnnotation()) As CompilationUnitSyntax If importsStatements.Count = 0 Then Return root End If Dim systemFirstInstance = ImportsStatementComparer.SystemFirstInstance Dim normalInstance = ImportsStatementComparer.NormalInstance Dim comparers = If(placeSystemNamespaceFirst, (systemFirstInstance, normalInstance), (normalInstance, systemFirstInstance)) Dim [imports] = AddImportsStatements(root, importsStatements) ' First, see if the imports were sorted according to the user's preference. If so, ' keep the same sorting after we add the import. However, if the imports weren't sorted ' according to their preference, then see if they're sorted in the other way. If so ' preserve that sorting as well. That way if the user is working with a file that ' was written on a machine with a different default, the imports will stay in a ' reasonable order. If root.Imports.IsSorted(comparers.Item1) Then [imports].Sort(comparers.Item1) ElseIf root.Imports.IsSorted(comparers.Item2) Then [imports].Sort(comparers.Item2) End If Dim rootAndAddBlankLine = AddImportHelpers.MoveTrivia( VisualBasicSyntaxFacts.Instance, root, root.Imports, [imports]) root = rootAndAddBlankLine.root Dim addBlankLine = rootAndAddBlankLine.addBlankLine Dim rootWithNewImports = root.WithImports( [imports].Select(Function(u) u.WithAdditionalAnnotations(annotations)).ToSyntaxList()) If addBlankLine Then Dim lastImport = rootWithNewImports.Imports.Last() Dim nextToken = lastImport.GetLastToken(includeZeroWidth:=True, includeSkipped:=True).GetNextTokenOrEndOfFile(includeZeroWidth:=True, includeSkipped:=True) Dim endOfLine = lastImport.GetTrailingTrivia().LastOrDefault(Function(trivia) VisualBasicSyntaxFacts.Instance.IsEndOfLineTrivia(trivia)) Debug.Assert(Not endOfLine.IsKind(SyntaxKind.None)) If Not endOfLine.IsKind(SyntaxKind.None) Then rootWithNewImports = rootWithNewImports.ReplaceToken(nextToken, nextToken.WithPrependedLeadingTrivia(endOfLine)) End If End If Return rootWithNewImports End Function Private Function AddImportsStatements(root As CompilationUnitSyntax, importsStatements As IList(Of ImportsStatementSyntax)) As List(Of ImportsStatementSyntax) ' We need to try and not place the using inside of a directive if possible. Dim [imports] = New List(Of ImportsStatementSyntax) Dim importsLength = root.Imports.Count Dim endOfList = importsLength - 1 Dim startOfLastDirective = -1 Dim endOfLastDirective = -1 For index = 0 To endOfList If root.Imports(index).GetLeadingTrivia().Any(Function(trivia) trivia.IsKind(SyntaxKind.IfDirectiveTrivia, SyntaxKind.ElseIfDirectiveTrivia, SyntaxKind.ElseDirectiveTrivia)) Then startOfLastDirective = index End If If root.Imports(index).GetLeadingTrivia().Any(Function(trivia) trivia.IsKind(SyntaxKind.EndIfDirectiveTrivia)) Then endOfLastDirective = index End If Next ' if the entire using Is in a directive Or there Is a using list at the end outside of the directive add the using at the end, ' else place it before the last directive. [imports].AddRange(root.Imports) If (startOfLastDirective = 0 AndAlso (endOfLastDirective = endOfList OrElse endOfLastDirective = -1)) OrElse (startOfLastDirective = -1 AndAlso endOfLastDirective = -1) OrElse (endOfLastDirective <> endOfList AndAlso endOfLastDirective <> -1) Then [imports].AddRange(importsStatements) Else [imports].InsertRange(startOfLastDirective, importsStatements) End If Return [imports] End Function End Module End Namespace