From f88627ae686ab14800a7bcbb6709e6f10947724f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 18 Dec 2024 13:34:37 -0800 Subject: [PATCH 1/9] Make more code jtf --- .../CSharpEndConstructGenerationService.cs | 22 +-- .../IEndConstructGenerationService.cs | 5 +- .../EndConstructCommandHandler.vb | 31 ++-- .../EndConstructState.vb | 16 +- .../EndConstructStatementVisitor.vb | 49 +++++-- ...dConstructStatementVisitor_CustomEvents.vb | 8 +- ...ndConstructStatementVisitor_IfStatement.vb | 1 - ...isualBasicEndConstructGenerationService.vb | 18 ++- ...tAbstractClassOrInterfaceCommandHandler.vb | 9 +- .../EndConstructTestingHelpers.vb | 128 ++++++++-------- .../MiscellaneousTests.vb | 7 +- .../EndConstructGeneration/XmlLiteralTests.vb | 138 +++++++++--------- 12 files changed, 233 insertions(+), 199 deletions(-) diff --git a/src/EditorFeatures/CSharp/EndConstruct/CSharpEndConstructGenerationService.cs b/src/EditorFeatures/CSharp/EndConstruct/CSharpEndConstructGenerationService.cs index d44bf6e7c6a66..ce65cec44f0f4 100644 --- a/src/EditorFeatures/CSharp/EndConstruct/CSharpEndConstructGenerationService.cs +++ b/src/EditorFeatures/CSharp/EndConstruct/CSharpEndConstructGenerationService.cs @@ -6,29 +6,21 @@ using System.Composition; using System.Diagnostics.CodeAnalysis; using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Implementation.EndConstructGeneration; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Editor.CSharp.EndConstructGeneration; [ExportLanguageService(typeof(IEndConstructGenerationService), LanguageNames.CSharp), Shared] [ExcludeFromCodeCoverage] -internal class CSharpEndConstructGenerationService : IEndConstructGenerationService +[method: ImportingConstructor] +[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] +internal sealed class CSharpEndConstructGenerationService() : IEndConstructGenerationService { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpEndConstructGenerationService() - { - } - - public bool TryDo( - ITextView textView, - ITextBuffer subjectBuffer, - char typedChar, - CancellationToken cancellationToken) - { - return false; - } + public Task TryDoAsync(ITextView textView, ITextBuffer subjectBuffer, char typedChar, CancellationToken cancellationToken) + => SpecializedTasks.False; } diff --git a/src/EditorFeatures/Core/EndConstructGeneration/IEndConstructGenerationService.cs b/src/EditorFeatures/Core/EndConstructGeneration/IEndConstructGenerationService.cs index 99e2571f7ace6..0014088bc5f3d 100644 --- a/src/EditorFeatures/Core/EndConstructGeneration/IEndConstructGenerationService.cs +++ b/src/EditorFeatures/Core/EndConstructGeneration/IEndConstructGenerationService.cs @@ -2,9 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System.Threading; +using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; @@ -13,5 +12,5 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.EndConstructGeneration; internal interface IEndConstructGenerationService : ILanguageService { - bool TryDo(ITextView textView, ITextBuffer subjectBuffer, char typedChar, CancellationToken cancellationToken); + Task TryDoAsync(ITextView textView, ITextBuffer subjectBuffer, char typedChar, CancellationToken cancellationToken); } diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb index f7752ec605b3f..4759ff490677e 100644 --- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb +++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructCommandHandler.vb @@ -66,21 +66,25 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration End Function Public Sub ExecuteCommand_TypeCharCommandHandler(args As TypeCharCommandArgs, nextHandler As Action, context As CommandExecutionContext) Implements IChainedCommandHandler(Of TypeCharCommandArgs).ExecuteCommand - nextHandler() + _threadingContext.JoinableTaskFactory.Run( + Async Function() + nextHandler() - If Not _editorOptionsService.GlobalOptions.GetOption(EndConstructGenerationOptionsStorage.EndConstruct, LanguageNames.VisualBasic) Then - Return - End If + If Not _editorOptionsService.GlobalOptions.GetOption(EndConstructGenerationOptionsStorage.EndConstruct, LanguageNames.VisualBasic) Then + Return + End If - Dim textSnapshot = args.SubjectBuffer.CurrentSnapshot - Dim document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges() - If document Is Nothing Then - Return - End If + Dim textSnapshot = args.SubjectBuffer.CurrentSnapshot + Dim document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges() + If document Is Nothing Then + Return + End If - ' End construct is not cancellable. - Dim endConstructService = document.GetLanguageService(Of IEndConstructGenerationService)() - endConstructService.TryDo(args.TextView, args.SubjectBuffer, args.TypedChar, context.OperationContext.UserCancellationToken) + ' End construct is not cancellable. + Dim endConstructService = document.GetLanguageService(Of IEndConstructGenerationService)() + Await endConstructService.TryDoAsync( + args.TextView, args.SubjectBuffer, args.TypedChar, context.OperationContext.UserCancellationToken).ConfigureAwait(True) + End Function) End Sub Public Function GetCommandState_AutomaticLineEnderCommandHandler(args As AutomaticLineEnderCommandArgs, nextHandler As Func(Of CommandState)) As CommandState Implements IChainedCommandHandler(Of AutomaticLineEnderCommandArgs).GetCommandState @@ -123,7 +127,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration textView, subjectBuffer, document, cancellationToken).ConfigureAwait(True) Dim endConstructService = document.GetLanguageService(Of IEndConstructGenerationService)() - Dim result = endConstructService.TryDo(textView, subjectBuffer, vbLf(0), cancellationToken) + Dim result = Await endConstructService.TryDoAsync( + textView, subjectBuffer, vbLf(0), cancellationToken).ConfigureAwait(True) If Not result Then nextHandler() diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructState.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructState.vb index bbbe521955a7e..9705c29bd91d1 100644 --- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructState.vb +++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructState.vb @@ -2,15 +2,17 @@ ' 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 + Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration - Friend Class EndConstructState + Friend NotInheritable Class EndConstructState Private ReadOnly _caretPosition As Integer - Private ReadOnly _semanticModel As Lazy(Of SemanticModel) + Private ReadOnly _semanticModel As AsyncLazy(Of SemanticModel) Private ReadOnly _tree As SyntaxTree Private ReadOnly _tokenToLeft As SyntaxToken Private ReadOnly _newLineCharacter As String - Public Sub New(caretPosition As Integer, semanticModel As Lazy(Of SemanticModel), syntaxTree As SyntaxTree, tokenToLeft As SyntaxToken, newLineCharacter As String) + Public Sub New(caretPosition As Integer, semanticModel As AsyncLazy(Of SemanticModel), syntaxTree As SyntaxTree, tokenToLeft As SyntaxToken, newLineCharacter As String) ThrowIfNull(syntaxTree) _caretPosition = caretPosition @@ -26,11 +28,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration End Get End Property - Public ReadOnly Property SemanticModel As SemanticModel - Get - Return _semanticModel.Value - End Get - End Property + Public Function GetSemanticModelAsync(cancellationToken As CancellationToken) As Task(Of SemanticModel) + Return _semanticModel.GetValueAsync(cancellationToken) + End Function Public ReadOnly Property SyntaxTree As SyntaxTree Get diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor.vb index ecf27a11ee082..09789a442303d 100644 --- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor.vb +++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor.vb @@ -12,25 +12,51 @@ Imports Microsoft.VisualStudio.Text.Editor Imports Microsoft.VisualStudio.Text.Editor.OptionsExtensionMethods Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration - Partial Friend Class EndConstructStatementVisitor + Partial Friend NotInheritable Class EndConstructStatementVisitor Inherits VisualBasicSyntaxVisitor(Of AbstractEndConstructResult) Private ReadOnly _textView As ITextView Private ReadOnly _subjectBuffer As ITextBuffer - Private ReadOnly _cancellationToken As CancellationToken Private ReadOnly _state As EndConstructState + Private ReadOnly _cancellationToken As CancellationToken + + ''' + ''' Note: this is only passed in when return true. Any functions that require + ''' a semantic model must declare their need up front so we do not pay the cost for semantics for all the cases + ''' that do not need it. + ''' + Private ReadOnly _semanticModel As SemanticModel - Public Sub New(textView As ITextView, - subjectBuffer As ITextBuffer, - state As EndConstructState, - cancellationToken As CancellationToken) + Public Sub New( + textView As ITextView, + subjectBuffer As ITextBuffer, + state As EndConstructState, + semanticModel As SemanticModel, + cancellationToken As CancellationToken) _textView = textView _subjectBuffer = subjectBuffer _state = state + _semanticModel = semanticModel _cancellationToken = cancellationToken End Sub + Public Shared Function NeedsSemanticModel(node As SyntaxNode) As Boolean + ' All of these call HandleMethodBlockSyntax, which needs semantics + If TypeOf node Is MethodStatementSyntax OrElse + TypeOf node Is SubNewStatementSyntax OrElse + TypeOf node Is OperatorStatementSyntax Then + Return True + End If + + ' Calls GenerateAddOrRemoveHandler and GenerateRaiseEventHandler, both which needs semantics + If TypeOf node Is EventStatementSyntax Then + Return True + End If + + Return False + End Function + Public Overrides Function VisitDoStatement(node As DoStatementSyntax) As AbstractEndConstructResult Dim needsEnd = node.GetAncestorsOrThis(Of DoLoopBlockSyntax)().Any(Function(block) block.LoopStatement.IsMissing) @@ -100,11 +126,12 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration End If End Function - Private Function TryGenerateResultForConstructorSpitWithInitializeComponent(methodBlock As MethodBlockBaseSyntax) As AbstractEndConstructResult + Private Function TryGenerateResultForConstructorSpitWithInitializeComponent( + methodBlock As MethodBlockBaseSyntax) As AbstractEndConstructResult If methodBlock.BlockStatement.Kind = SyntaxKind.SubNewStatement Then - Dim boundConstructor = _state.SemanticModel.GetDeclaredSymbol(DirectCast(methodBlock.BlockStatement, SubNewStatementSyntax)) + Dim boundConstructor = _semanticModel.GetDeclaredSymbol(DirectCast(methodBlock.BlockStatement, SubNewStatementSyntax)) If boundConstructor IsNot Nothing Then - If boundConstructor.ContainingType.IsDesignerGeneratedTypeWithInitializeComponent(_state.SemanticModel.Compilation) Then + If boundConstructor.ContainingType.IsDesignerGeneratedTypeWithInitializeComponent(_semanticModel.Compilation) Then Dim aligningWhitespace = _subjectBuffer.CurrentSnapshot.GetAligningWhitespace(methodBlock.BlockStatement.SpanStart) Dim innerAligningWhitespace = aligningWhitespace & " " @@ -161,10 +188,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration Dim aligningWhitespace = _subjectBuffer.CurrentSnapshot.GetAligningWhitespace(node.SpanStart) Dim stringBuilder As New StringBuilder stringBuilder.Append(_textView.Options.GetNewLineCharacter()) - StringBuilder.Append(aligningWhitespace & " Case ") + stringBuilder.Append(aligningWhitespace & " Case ") Dim finalCaretPoint = stringBuilder.Length stringBuilder.AppendLine() - StringBuilder.Append(aligningWhitespace & "End Select") + stringBuilder.Append(aligningWhitespace & "End Select") Return New ReplaceSpanResult(New SnapshotSpan(_subjectBuffer.CurrentSnapshot, _state.CaretPosition, 0), stringBuilder.ToString(), newCaretPosition:=finalCaretPoint) diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_CustomEvents.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_CustomEvents.vb index 5c8274840d942..6640cc9406133 100644 --- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_CustomEvents.vb +++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_CustomEvents.vb @@ -37,21 +37,21 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration End Function Private Function GenerateAddOrRemoveHandler(eventStatement As EventStatementSyntax, kind As SyntaxKind) As String() - Dim type = _state.SemanticModel.GetTypeInfo(DirectCast(eventStatement.AsClause, SimpleAsClauseSyntax).Type, Me._cancellationToken) + Dim type = _semanticModel.GetTypeInfo(DirectCast(eventStatement.AsClause, SimpleAsClauseSyntax).Type, Me._cancellationToken) Dim position As Integer = eventStatement.SpanStart Dim aligningWhitespace = _subjectBuffer.CurrentSnapshot.GetAligningWhitespace(position) & " " - Return {aligningWhitespace & SyntaxFacts.GetText(kind) & "(value As " & type.Type.ToMinimalDisplayString(_state.SemanticModel, position, SymbolDisplayFormats.NameFormat) & ")", + Return {aligningWhitespace & SyntaxFacts.GetText(kind) & "(value As " & type.Type.ToMinimalDisplayString(_semanticModel, position, SymbolDisplayFormats.NameFormat) & ")", "", aligningWhitespace & "End " & SyntaxFacts.GetText(kind)} End Function Private Function GenerateRaiseEventHandler(eventStatement As EventStatementSyntax) As String() - Dim type = TryCast(_state.SemanticModel.GetTypeInfo(DirectCast(eventStatement.AsClause, SimpleAsClauseSyntax).Type, Me._cancellationToken).Type, INamedTypeSymbol) + Dim type = TryCast(_semanticModel.GetTypeInfo(DirectCast(eventStatement.AsClause, SimpleAsClauseSyntax).Type, Me._cancellationToken).Type, INamedTypeSymbol) Dim signature = "" If type IsNot Nothing AndAlso type.DelegateInvokeMethod IsNot Nothing Then Dim parameterStrings = type.DelegateInvokeMethod.Parameters.Select( - Function(p) p.ToMinimalDisplayString(_state.SemanticModel, eventStatement.SpanStart)) + Function(p) p.ToMinimalDisplayString(_semanticModel, eventStatement.SpanStart)) signature = String.Join(", ", parameterStrings) End If diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_IfStatement.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_IfStatement.vb index f723001094a47..b47d0ee67032a 100644 --- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_IfStatement.vb +++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/EndConstructStatementVisitor_IfStatement.vb @@ -7,7 +7,6 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration Partial Friend Class EndConstructStatementVisitor - Public Overrides Function VisitIfStatement(node As IfStatementSyntax) As AbstractEndConstructResult Dim needsEnd = node.GetAncestorsOrThis(Of MultiLineIfBlockSyntax)().Any(Function(block) block.EndIfStatement.IsMissing) diff --git a/src/EditorFeatures/VisualBasic/EndConstructGeneration/VisualBasicEndConstructGenerationService.vb b/src/EditorFeatures/VisualBasic/EndConstructGeneration/VisualBasicEndConstructGenerationService.vb index eb290da618bfd..11b3e8dee49be 100644 --- a/src/EditorFeatures/VisualBasic/EndConstructGeneration/VisualBasicEndConstructGenerationService.vb +++ b/src/EditorFeatures/VisualBasic/EndConstructGeneration/VisualBasicEndConstructGenerationService.vb @@ -161,12 +161,13 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration Dim bufferOptions = _editorOptionsFactoryService.GetOptions(subjectBuffer) Return New EndConstructState( - caretPosition.Value, New Lazy(Of SemanticModel)(Function() document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken)), tree, tokenToLeft, bufferOptions.GetNewLineCharacter()) + caretPosition.Value, AsyncLazy.Create(Function(c) document.GetSemanticModelAsync(c)), tree, tokenToLeft, bufferOptions.GetNewLineCharacter()) End Function - Friend Overridable Function TryDoEndConstructForEnterKey(textView As ITextView, - subjectBuffer As ITextBuffer, - cancellationToken As CancellationToken) As Boolean + Friend Overridable Async Function TryDoEndConstructForEnterKeyAsync( + textView As ITextView, + subjectBuffer As ITextBuffer, + cancellationToken As CancellationToken) As Task(Of Boolean) Using Logger.LogBlock(FunctionId.EndConstruct_DoStatement, cancellationToken) Using transaction = New CaretPreservingEditTransaction(VBEditorResources.End_Construct, textView, _undoHistoryRegistry, _editorOperationsFactoryService) transaction.MergePolicy = AutomaticCodeChangeMergePolicy.Instance @@ -285,7 +286,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration Return False End If - Dim visitor = New EndConstructStatementVisitor(textView, subjectBuffer, state, cancellationToken) + Dim semanticModel = If(EndConstructStatementVisitor.NeedsSemanticModel(statement), + Await state.GetSemanticModelAsync(cancellationToken).ConfigureAwait(True), + Nothing) + Dim visitor = New EndConstructStatementVisitor(textView, subjectBuffer, state, semanticModel, cancellationToken) Dim result = visitor.Visit(statement) If result Is Nothing Then @@ -480,10 +484,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration End Using End Function - Public Function TryDo(textView As ITextView, subjectBuffer As ITextBuffer, typedChar As Char, cancellationToken As CancellationToken) As Boolean Implements IEndConstructGenerationService.TryDo + Public Async Function TryDoAsync(textView As ITextView, subjectBuffer As ITextBuffer, typedChar As Char, cancellationToken As CancellationToken) As Task(Of Boolean) Implements IEndConstructGenerationService.TryDoAsync Select Case typedChar Case vbLf(0) - Return Me.TryDoEndConstructForEnterKey(textView, subjectBuffer, cancellationToken) + Return Await Me.TryDoEndConstructForEnterKeyAsync(textView, subjectBuffer, cancellationToken).ConfigureAwait(True) Case ">"c Return Me.TryDoXmlElementEndConstruct(textView, subjectBuffer, cancellationToken) Case "-"c diff --git a/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb b/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb index c884c7215587b..d529709ebbfcc 100644 --- a/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb +++ b/src/EditorFeatures/VisualBasic/Utilities/CommandHandlers/AbstractImplementAbstractClassOrInterfaceCommandHandler.vb @@ -67,7 +67,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities.CommandHandlers ' 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 - TryGenerateEndConstruct(args, _cancellationToken) + Await TryGenerateEndConstructAsync(args, _cancellationToken).ConfigureAwait(True) Dim snapshot = args.SubjectBuffer.CurrentSnapshot Dim caretPosition = args.TextView.GetCaretPoint(args.SubjectBuffer).Value @@ -92,7 +92,9 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities.CommandHandlers Return True End Function - Private Shared Function TryGenerateEndConstruct(args As ReturnKeyCommandArgs, cancellationToken As CancellationToken) As Boolean + Private Shared Async Function TryGenerateEndConstructAsync( + args As ReturnKeyCommandArgs, + cancellationToken As CancellationToken) As Task(Of Boolean) Dim textSnapshot = args.SubjectBuffer.CurrentSnapshot Dim document = textSnapshot.GetOpenDocumentInCurrentContextWithChanges() @@ -112,7 +114,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Utilities.CommandHandlers Dim endConstructGenerationService = document.GetLanguageService(Of IEndConstructGenerationService)() - Return endConstructGenerationService.TryDo(args.TextView, args.SubjectBuffer, vbLf(0), cancellationToken) + Return Await endConstructGenerationService.TryDoAsync( + args.TextView, args.SubjectBuffer, vbLf(0), cancellationToken).ConfigureAwait(True) End Function Private Overloads Async Function TryExecuteAsync( diff --git a/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/EndConstructTestingHelpers.vb b/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/EndConstructTestingHelpers.vb index b1214f4924398..75dc3eb375333 100644 --- a/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/EndConstructTestingHelpers.vb +++ b/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/EndConstructTestingHelpers.vb @@ -7,7 +7,6 @@ Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Editor.[Shared].Utilities Imports Microsoft.CodeAnalysis.Editor.UnitTests Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities -Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Editor.VisualBasic.EndConstructGeneration Imports Microsoft.CodeAnalysis.Editor.VisualBasic.LineCommit Imports Microsoft.CodeAnalysis.Options @@ -27,11 +26,12 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera Return mock.Object End Function - Private Sub VerifyTypedCharApplied(doFunc As Func(Of VisualBasicEndConstructService, ITextView, ITextBuffer, Boolean), - before As String, - after As String, - typedChar As Char, - endCaretPos As Integer()) + Private Async Function VerifyTypedCharAppliedAsync( + doFunc As Func(Of VisualBasicEndConstructService, ITextView, ITextBuffer, Task(Of Boolean)), + before As String, + after As String, + typedChar As Char, + endCaretPos As Integer()) As Task Dim caretPos = before.IndexOf("$$", StringComparison.Ordinal) Dim beforeText = before.Replace("$$", "") Using workspace = EditorTestWorkspace.CreateVisualBasic(beforeText, composition:=EditorTestCompositions.EditorFeatures) @@ -48,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera workspace.GetService(Of IEditorOptionsFactoryService)) view.TextBuffer.Replace(New Span(caretPos, 0), typedChar.ToString()) - Assert.True(doFunc(endConstructService, view, view.TextBuffer)) + Assert.True(Await doFunc(endConstructService, view, view.TextBuffer)) Assert.Equal(after, view.TextSnapshot.GetText()) Dim actualLine As Integer @@ -57,13 +57,14 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera Assert.Equal(endCaretPos(0), actualLine) Assert.Equal(endCaretPos(1), actualChar) End Using - End Sub + End Function - Private Sub VerifyApplied(doFunc As Func(Of VisualBasicEndConstructService, ITextView, ITextBuffer, Boolean), - before As String, - beforeCaret As Integer(), - after As String, - afterCaret As Integer()) + Private Async Function VerifyAppliedAsync( + doFunc As Func(Of VisualBasicEndConstructService, ITextView, ITextBuffer, Task(Of Boolean)), + before As String, + beforeCaret As Integer(), + after As String, + afterCaret As Integer()) As Task Using workspace = EditorTestWorkspace.CreateVisualBasic(before, composition:=EditorTestCompositions.EditorFeatures) Dim globalOptions = workspace.GetService(Of IGlobalOptionService) globalOptions.SetGlobalOption(LineCommitOptionsStorage.PrettyListing, LanguageNames.VisualBasic, False) @@ -87,7 +88,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera workspace.GetService(Of IEditorOperationsFactoryService), workspace.GetService(Of IEditorOptionsFactoryService)) - Assert.True(doFunc(endConstructService, textView, textView.TextSnapshot.TextBuffer)) + Assert.True(Await doFunc(endConstructService, textView, textView.TextSnapshot.TextBuffer)) Assert.Equal(EditorFactory.LinesToFullText(after), textView.TextSnapshot.GetText()) Dim afterLine = textView.TextSnapshot.GetLineFromLineNumber(afterCaret(0)) @@ -100,7 +101,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera Assert.Equal(Of Integer)(afterCaretPoint, textView.GetCaretPoint(subjectBuffer).Value.Position) End Using - End Sub + End Function Private Function GetSnapshotPointFromArray(view As ITextView, caret As Integer(), startIndex As Integer) As SnapshotPoint Dim line = view.TextSnapshot.GetLineFromLineNumber(caret(startIndex)) @@ -112,9 +113,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera End If End Function - Private Sub VerifyNotApplied(doFunc As Func(Of VisualBasicEndConstructService, ITextView, ITextBuffer, Boolean), - text As String, - caret As Integer()) + Private Async Function VerifyNotAppliedAsync( + doFunc As Func(Of VisualBasicEndConstructService, ITextView, ITextBuffer, Task(Of Boolean)), + text As String, + caret As Integer()) As Task Using workspace = EditorTestWorkspace.CreateVisualBasic(text) Dim textView = workspace.Documents.First().GetTextView() Dim subjectBuffer = workspace.Documents.First().GetTextBuffer() @@ -135,7 +137,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera workspace.GetService(Of IEditorOperationsFactoryService), workspace.GetService(Of IEditorOptionsFactoryService)) - Assert.False(doFunc(endConstructService, textView, textView.TextSnapshot.TextBuffer), "End Construct should not have generated anything.") + Assert.False(Await doFunc(endConstructService, textView, textView.TextSnapshot.TextBuffer), "End Construct should not have generated anything.") ' The text should not have changed Assert.Equal(EditorFactory.LinesToFullText(text), textView.TextSnapshot.GetText()) @@ -143,63 +145,65 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera ' The caret should not have moved Assert.Equal(Of Integer)(caretPosition, textView.GetCaretPoint(subjectBuffer).Value.Position) End Using - End Sub + End Function - Public Sub VerifyStatementEndConstructApplied(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) - VerifyApplied(Function(s, v, b) s.TryDoEndConstructForEnterKey(v, b, CancellationToken.None), before, beforeCaret, after, afterCaret) - End Sub + Public Function VerifyStatementEndConstructAppliedAsync(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) As Task + Return VerifyAppliedAsync(Function(s, v, b) s.TryDoEndConstructForEnterKeyAsync(v, b, CancellationToken.None), before, beforeCaret, after, afterCaret) + End Function - Public Sub VerifyStatementEndConstructNotApplied(text As String, caret As Integer()) - VerifyNotApplied(Function(s, v, b) s.TryDoEndConstructForEnterKey(v, b, CancellationToken.None), text, caret) - End Sub + Public Function VerifyStatementEndConstructNotAppliedAsync(text As String, caret As Integer()) As Task + Return VerifyNotAppliedAsync(Function(s, v, b) s.TryDoEndConstructForEnterKeyAsync(v, b, CancellationToken.None), text, caret) + End Function - Public Sub VerifyXmlElementEndConstructApplied(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) - VerifyApplied(Function(s, v, b) s.TryDoXmlElementEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) - End Sub +#Disable Warning BC42356 ' This async method lacks 'Await' operators and so will run synchronously + Public Function VerifyXmlElementEndConstructAppliedAsync(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) As Task + Return VerifyAppliedAsync(Async Function(s, v, b) s.TryDoXmlElementEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) + End Function - Public Sub VerifyXmlElementEndConstructNotApplied(text As String, caret As Integer()) - VerifyNotApplied(Function(s, v, b) s.TryDoXmlElementEndConstruct(v, b, Nothing), text, caret) - End Sub + Public Function VerifyXmlElementEndConstructNotAppliedAsync(text As String, caret As Integer()) As Task + Return VerifyNotAppliedAsync(Async Function(s, v, b) s.TryDoXmlElementEndConstruct(v, b, Nothing), text, caret) + End Function - Public Sub VerifyXmlCommentEndConstructApplied(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) - VerifyApplied(Function(s, v, b) s.TryDoXmlCommentEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) - End Sub + Public Function VerifyXmlCommentEndConstructAppliedAsync(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) As Task + Return VerifyAppliedAsync(Async Function(s, v, b) s.TryDoXmlCommentEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) + End Function - Public Sub VerifyXmlCommentEndConstructNotApplied(text As String, caret As Integer()) - VerifyNotApplied(Function(s, v, b) s.TryDoXmlCommentEndConstruct(v, b, Nothing), text, caret) - End Sub + Public Function VerifyXmlCommentEndConstructNotAppliedAsync(text As String, caret As Integer()) As Task + Return VerifyNotAppliedAsync(Async Function(s, v, b) s.TryDoXmlCommentEndConstruct(v, b, Nothing), text, caret) + End Function - Public Sub VerifyXmlCDataEndConstructApplied(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) - VerifyApplied(Function(s, v, b) s.TryDoXmlCDataEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) - End Sub + Public Function VerifyXmlCDataEndConstructAppliedAsync(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) As Task + Return VerifyAppliedAsync(Async Function(s, v, b) s.TryDoXmlCDataEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) + End Function - Public Sub VerifyXmlCDataEndConstructNotApplied(text As String, caret As Integer()) - VerifyNotApplied(Function(s, v, b) s.TryDoXmlCDataEndConstruct(v, b, Nothing), text, caret) - End Sub + Public Function VerifyXmlCDataEndConstructNotAppliedAsync(text As String, caret As Integer()) As Task + Return VerifyNotAppliedAsync(Async Function(s, v, b) s.TryDoXmlCDataEndConstruct(v, b, Nothing), text, caret) + End Function - Public Sub VerifyXmlEmbeddedExpressionEndConstructApplied(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) - VerifyApplied(Function(s, v, b) s.TryDoXmlEmbeddedExpressionEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) - End Sub + Public Function VerifyXmlEmbeddedExpressionEndConstructAppliedAsync(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) As Task + Return VerifyAppliedAsync(Async Function(s, v, b) s.TryDoXmlEmbeddedExpressionEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) + End Function - Public Sub VerifyXmlEmbeddedExpressionEndConstructNotApplied(text As String, caret As Integer()) - VerifyNotApplied(Function(s, v, b) s.TryDoXmlEmbeddedExpressionEndConstruct(v, b, Nothing), text, caret) - End Sub + Public Function VerifyXmlEmbeddedExpressionEndConstructNotAppliedAsync(text As String, caret As Integer()) As Task + Return VerifyNotAppliedAsync(Async Function(s, v, b) s.TryDoXmlEmbeddedExpressionEndConstruct(v, b, Nothing), text, caret) + End Function - Public Sub VerifyXmlProcessingInstructionEndConstructApplied(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) - VerifyApplied(Function(s, v, b) s.TryDoXmlProcessingInstructionEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) - End Sub + Public Function VerifyXmlProcessingInstructionEndConstructAppliedAsync(before As String, beforeCaret As Integer(), after As String, afterCaret As Integer()) As Task + Return VerifyAppliedAsync(Async Function(s, v, b) s.TryDoXmlProcessingInstructionEndConstruct(v, b, Nothing), before, beforeCaret, after, afterCaret) + End Function - Public Sub VerifyXmlProcessingInstructionNotApplied(text As String, caret As Integer()) - VerifyNotApplied(Function(s, v, b) s.TryDoXmlProcessingInstructionEndConstruct(v, b, Nothing), text, caret) - End Sub + Public Function VerifyXmlProcessingInstructionNotAppliedAsync(text As String, caret As Integer()) As Task + Return VerifyNotAppliedAsync(Async Function(s, v, b) s.TryDoXmlProcessingInstructionEndConstruct(v, b, Nothing), text, caret) + End Function +#Enable Warning BC42356 ' This async method lacks 'Await' operators and so will run synchronously - Public Sub VerifyEndConstructAppliedAfterChar(before As String, after As String, typedChar As Char, endCaretPos As Integer()) - VerifyTypedCharApplied(Function(s, v, b) s.TryDo(v, b, typedChar, Nothing), before, after, typedChar, endCaretPos) - End Sub + Public Function VerifyEndConstructAppliedAfterCharAsync(before As String, after As String, typedChar As Char, endCaretPos As Integer()) As Task + Return VerifyTypedCharAppliedAsync(Function(s, v, b) s.TryDoAsync(v, b, typedChar, Nothing), before, after, typedChar, endCaretPos) + End Function - Public Sub VerifyEndConstructNotAppliedAfterChar(before As String, after As String, typedChar As Char, endCaretPos As Integer()) - VerifyTypedCharApplied(Function(s, v, b) Not s.TryDo(v, b, typedChar, Nothing), before, after, typedChar, endCaretPos) - End Sub + Public Function VerifyEndConstructNotAppliedAfterCharAsync(before As String, after As String, typedChar As Char, endCaretPos As Integer()) As Task + Return VerifyTypedCharAppliedAsync(Async Function(s, v, b) Not Await s.TryDoAsync(v, b, typedChar, Nothing), before, after, typedChar, endCaretPos) + End Function Public Sub VerifyAppliedAfterReturnUsingCommandHandler( before As String, diff --git a/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/MiscellaneousTests.vb b/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/MiscellaneousTests.vb index 133bddbca95fb..3f64dca34b56e 100644 --- a/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/MiscellaneousTests.vb +++ b/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/MiscellaneousTests.vb @@ -127,7 +127,7 @@ End Class", End Sub - Public Sub DeletesSelectedText() + Public Async Function DeletesSelectedText() As Task Using workspace = EditorTestWorkspace.CreateVisualBasic("Interface IGoo ~~") Dim textView = workspace.Documents.Single().GetTextView() Dim subjectBuffer = workspace.Documents.First().GetTextBuffer() @@ -143,10 +143,11 @@ End Class", workspace.GetService(Of IEditorOperationsFactoryService), workspace.GetService(Of IEditorOptionsFactoryService)) - Assert.True(endConstructService.TryDoEndConstructForEnterKey(textView, textView.TextSnapshot.TextBuffer, CancellationToken.None)) + Assert.True(Await endConstructService.TryDoEndConstructForEnterKeyAsync( + textView, textView.TextSnapshot.TextBuffer, CancellationToken.None)) Assert.Equal("End Interface", textView.TextSnapshot.Lines.Last().GetText()) End Using - End Sub + End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/XmlLiteralTests.vb b/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/XmlLiteralTests.vb index 18a5ad08c5358..d9e0b6bf92c0f 100644 --- a/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/XmlLiteralTests.vb +++ b/src/EditorFeatures/VisualBasicTest/EndConstructGeneration/XmlLiteralTests.vb @@ -7,8 +7,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.EndConstructGenera Public Class XmlLiteralTests - Public Sub TestApplyAfterXmlStartElement() - VerifyXmlElementEndConstructApplied( + Public Async Function TestApplyAfterXmlStartElement() As Task + Await VerifyXmlElementEndConstructAppliedAsync( before:="Class C1 Sub M1() Dim x = @@ -21,11 +21,11 @@ End Class", End Sub End Class", afterCaret:={2, 21}) - End Sub + End Function - Public Sub TestApplyAfterXmlStartElementSplitAcrossLines() - VerifyXmlElementEndConstructApplied( + Public Async Function TestApplyAfterXmlStartElementSplitAcrossLines() As Task + Await VerifyXmlElementEndConstructAppliedAsync( before:="Class C1 Sub M1() Dim x = - Public Sub TestApplyAfterXmlStartElementWithNamespace() - VerifyXmlElementEndConstructApplied( + Public Async Function TestApplyAfterXmlStartElementWithNamespace() As Task + Await VerifyXmlElementEndConstructAppliedAsync( before:="Class C1 Sub M1() Dim x = @@ -57,76 +57,76 @@ End Class", End Sub End Class", afterCaret:={2, 21}) - End Sub + End Function - Public Sub DoNotApplyInParameterDeclaration1() - VerifyXmlElementEndConstructNotApplied( + Public Async Function DoNotApplyInParameterDeclaration1() As Task + Await VerifyXmlElementEndConstructNotAppliedAsync( text:="Class C1 Sub M1() End Sub End Class", caret:={1, 16}) - End Sub + End Function - Public Sub DoNotApplyInParameterDeclaration2() - VerifyXmlElementEndConstructNotApplied( + Public Async Function DoNotApplyInParameterDeclaration2() As Task + Await VerifyXmlElementEndConstructNotAppliedAsync( text:="Class C1 Sub M1(i As Integer, ) End Sub End Class", caret:={2, 16}) - End Sub + End Function - Public Sub DoNotApplyAfterXmlStartElementWithEndElement() - VerifyXmlElementEndConstructNotApplied( + Public Async Function DoNotApplyAfterXmlStartElementWithEndElement() As Task + Await VerifyXmlElementEndConstructNotAppliedAsync( text:="Class C1 Sub M1() Dim x = End Sub End Class", caret:={2, 23}) - End Sub + End Function - Public Sub DoNotApplyAfterXmlEndElement() - VerifyXmlElementEndConstructNotApplied( + Public Async Function DoNotApplyAfterXmlEndElement() As Task + Await VerifyXmlElementEndConstructNotAppliedAsync( text:="Class C1 Sub M1() Dim x = End Sub End Class", caret:={2, -1}) - End Sub + End Function - Public Sub DoNotApplyAfterSingleXmlTag() - VerifyXmlElementEndConstructNotApplied( + Public Async Function DoNotApplyAfterSingleXmlTag() As Task + Await VerifyXmlElementEndConstructNotAppliedAsync( text:="Class C1 Sub M1() Dim x = End Sub End Class", caret:={2, -1}) - End Sub + End Function - Public Sub DoNotApplyAfterProcessingInstruction() - VerifyXmlElementEndConstructNotApplied( + Public Async Function DoNotApplyAfterProcessingInstruction() As Task + Await VerifyXmlElementEndConstructNotAppliedAsync( text:="Class C1 Sub M1() Dim x = End Sub End Class", caret:={2, -1}) - End Sub + End Function - Public Sub TestApplyAfterXmlStartElementWhenPassedAsParameter1() - VerifyXmlElementEndConstructApplied( + Public Async Function TestApplyAfterXmlStartElementWhenPassedAsParameter1() As Task + Await VerifyXmlElementEndConstructAppliedAsync( before:="Class C1 Sub M1() M2( @@ -139,11 +139,11 @@ End Class", End Sub End Class", afterCaret:={2, 16}) - End Sub + End Function - Public Sub TestApplyAfterXmlStartElementWhenPassedAsParameter2() - VerifyXmlElementEndConstructApplied( + Public Async Function TestApplyAfterXmlStartElementWhenPassedAsParameter2() As Task + Await VerifyXmlElementEndConstructAppliedAsync( before:="Class C1 Sub M1() M2() @@ -156,11 +156,11 @@ End Class", End Sub End Class", afterCaret:={2, 16}) - End Sub + End Function - Public Sub TestApplyAfterXmlComment() - VerifyXmlCommentEndConstructApplied( + Public Async Function TestApplyAfterXmlComment() As Task + Await VerifyXmlCommentEndConstructAppliedAsync( before:="Class C1 Sub M1() Dim x =