/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb
208 строк
10 KB
Cyrus Najmabadi
Organize VB imports
27 июн 2025, 21:53
27 июн 2025, 21:53
e9c47fd
Код
Авторство
О чём код?
' 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.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.CodeCleanup Imports Microsoft.CodeAnalysis.Editor.Implementation.EndConstructGeneration Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities Imports Microsoft.CodeAnalysis.Formatting Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Simplification Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.Text.Shared.Extensions Imports Microsoft.CodeAnalysis.VisualBasic.AutomaticInsertionOfAbstractOrInterfaceMembers Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.VisualStudio.Commanding Imports Microsoft.VisualStudio.Text Imports Microsoft.VisualStudio.Text.Editor.Commanding.Commands Imports Microsoft.VisualStudio.Text.Operations Imports Microsoft.VisualStudio.Utilities Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities.CommandHandlers Friend MustInherit Class AbstractImplementAbstractClassOrInterfaceCommandHandler Implements ICommandHandler(Of ReturnKeyCommandArgs) Private ReadOnly _threadingContext As IThreadingContext Private ReadOnly _editorOperationsFactoryService As IEditorOperationsFactoryService Private ReadOnly _globalOptions As IGlobalOptionService Public ReadOnly Property DisplayName As String Implements INamed.DisplayName Get Return VBEditorResources.Implement_Abstract_Class_Or_Interface End Get End Property Protected Sub New( threadingContext As IThreadingContext, editorOperationsFactoryService As IEditorOperationsFactoryService, globalOptions As IGlobalOptionService) _threadingContext = threadingContext _editorOperationsFactoryService = editorOperationsFactoryService _globalOptions = globalOptions End Sub Protected MustOverride Overloads Function TryGetNewDocumentAsync( document As Document, typeSyntax As TypeSyntax, cancellationToken As CancellationToken) As Task(Of Document) Private Function ExecuteCommand(args As ReturnKeyCommandArgs, context As CommandExecutionContext) As Boolean Implements ICommandHandler(Of ReturnKeyCommandArgs).ExecuteCommand Return _threadingContext.JoinableTaskFactory.Run(Function() ExecuteCommandAsync(args, context)) End Function Private Async Function ExecuteCommandAsync(args As ReturnKeyCommandArgs, context As CommandExecutionContext) As Task(Of Boolean) Dim caretPointOpt = args.TextView.GetCaretPoint(args.SubjectBuffer) If caretPointOpt Is Nothing Then Return False End If ' Implement interface is not cancellable. ' TODO: Switch to a background work indicator to do this work. Dim _cancellationToken = CancellationToken.None If Not Await TryExecuteAsync(args, _cancellationToken).ConfigureAwait(True) Then Return False End If ' It's possible that there may be an end construct to generate at this position. ' We'll go ahead and generate it before determining whether we need to move the caret Await TryGenerateEndConstructAsync(args, _cancellationToken).ConfigureAwait(True) Dim snapshot = args.SubjectBuffer.CurrentSnapshot Dim caretPosition = args.TextView.GetCaretPoint(args.SubjectBuffer).Value Dim caretLine = snapshot.GetLineFromPosition(caretPosition) ' If there is any text after the caret on the same line, we'll pass through to ' insert a new line. Dim lastNonWhitespacePosition = If(caretLine.GetLastNonWhitespacePosition(), -1) If lastNonWhitespacePosition > caretPosition.Position Then Return False End If Dim nextLine = snapshot.GetLineFromLineNumber(caretLine.LineNumber + 1) If Not nextLine.IsEmptyOrWhitespace() Then ' If the next line is not whitespace, we'll go ahead and pass through to insert a new line. Return False End If ' If the next line *is* whitespace, we're just going to move the caret down a line. _editorOperationsFactoryService.GetEditorOperations(args.TextView).MoveLineDown(extendSelection:=False) Return True End Function Private Shared Async Function TryGenerateEndConstructAsync( args As ReturnKeyCommandArgs, cancellationToken As CancellationToken) As Task(Of Boolean) Dim textSnapshot = args.SubjectBuffer.CurrentSnapshot Dim document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges() If document Is Nothing Then Return False End If Dim caretPointOpt = args.TextView.GetCaretPoint(args.SubjectBuffer) If caretPointOpt Is Nothing Then Return False End If Dim caretPosition = caretPointOpt.Value.Position If caretPosition = 0 Then Return False End If Dim endConstructGenerationService = document.GetLanguageService(Of IEndConstructGenerationService)() Return Await endConstructGenerationService.TryDoAsync( args.TextView, args.SubjectBuffer, vbLf(0), cancellationToken).ConfigureAwait(True) End Function Private Overloads Async Function TryExecuteAsync( args As ReturnKeyCommandArgs, cancellationToken As CancellationToken) As Task(Of Boolean) If Not _globalOptions.GetOption(AutomaticInsertionOfAbstractOrInterfaceMembersOptionsStorage.AutomaticInsertionOfAbstractOrInterfaceMembers, LanguageNames.VisualBasic) Then Return False End If Dim caretPointOpt = args.TextView.GetCaretPoint(args.SubjectBuffer) If caretPointOpt Is Nothing Then Return False End If Dim caretPosition = caretPointOpt.Value.Position If caretPosition = 0 Then Return False End If Dim textSnapshot = args.SubjectBuffer.CurrentSnapshot Dim document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges() If document Is Nothing Then Return False End If Dim syntaxRoot = document.GetSyntaxRootSynchronously(cancellationToken) Dim token = syntaxRoot.FindTokenOnLeftOfPosition(caretPosition) Dim text = textSnapshot.AsText() If text.Lines.IndexOf(token.SpanStart) <> text.Lines.IndexOf(caretPosition) Then Return False End If Dim statement = token.GetAncestor(Of InheritsOrImplementsStatementSyntax)() If statement Is Nothing Then Return False End If If statement.Span.End <> token.Span.End Then Return False End If ' We need to track this token into the resulting buffer so we know what to do with the cursor ' from there Dim caretOffsetFromToken = caretPosition - token.Span.End Dim tokenAnnotation As New SyntaxAnnotation() document = document.WithSyntaxRoot(syntaxRoot.ReplaceToken(token, token.WithAdditionalAnnotations(tokenAnnotation))) token = document.GetSyntaxRootSynchronously(cancellationToken). GetAnnotatedNodesAndTokens(tokenAnnotation).First().AsToken() Dim typeSyntax = token.GetAncestor(Of TypeSyntax)() If typeSyntax Is Nothing Then Return False End If ' get top most identifier Dim identifier = DirectCast(typeSyntax.AncestorsAndSelf(ascendOutOfTrivia:=False).Where(Function(t) TypeOf t Is TypeSyntax).LastOrDefault(), TypeSyntax) If identifier Is Nothing Then Return False End If Dim newDocument = Await TryGetNewDocumentAsync(document, identifier, cancellationToken).ConfigureAwait(True) If newDocument Is Nothing Then Return False End If Dim cleanupOptions = Await newDocument.GetCodeCleanupOptionsAsync(cancellationToken).ConfigureAwait(True) newDocument = Await Simplifier.ReduceAsync(newDocument, Simplifier.Annotation, cleanupOptions.SimplifierOptions, cancellationToken).ConfigureAwait(True) newDocument = Await Formatter.FormatAsync(newDocument, Formatter.Annotation, cleanupOptions.FormattingOptions, cancellationToken).ConfigureAwait(True) Dim changes = Await newDocument.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(True) args.SubjectBuffer.ApplyChanges(changes) ' Place the cursor back to where it logically was after this token = newDocument.GetSyntaxRootSynchronously(cancellationToken). GetAnnotatedNodesAndTokens(tokenAnnotation).First().AsToken() args.TextView.TryMoveCaretToAndEnsureVisible( New SnapshotPoint(args.SubjectBuffer.CurrentSnapshot, Math.Min(token.Span.End + caretOffsetFromToken, args.SubjectBuffer.CurrentSnapshot.Length))) Return True End Function Private Function GetCommandState(args As ReturnKeyCommandArgs) As CommandState Implements ICommandHandler(Of ReturnKeyCommandArgs).GetCommandState Return CommandState.Unspecified End Function End Class End Namespace