diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProviderTests.cs index da1717ad8e0d8..f8a06a905dd66 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProviderTests.cs @@ -169,7 +169,7 @@ class Bar : IGoo { void IGoo.Goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -549,7 +549,7 @@ class Bar : IGoo { int IGoo.Generic(K key, V value) { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -1214,7 +1214,7 @@ class C : IFoo { static bool IFoo.TryDecode(out DecodeError? decodeError, out string? errorMessage) { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs index 488b059558925..4c5e053f27347 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs @@ -1878,7 +1878,7 @@ public override int goo { get { - return base.goo;$$ + [|return base.goo;|] } set @@ -1921,7 +1921,7 @@ public override int goo { get { - return base.goo;$$ + [|return base.goo;|] } set @@ -1963,7 +1963,7 @@ public override int goo { get { - return base.goo;$$ + [|return base.goo;|] } set @@ -2005,7 +2005,7 @@ public override int goo { set { - base.goo = value;$$ + [|base.goo = value;|] } } } @@ -2041,7 +2041,7 @@ public override int goo { get { - return base.goo;$$ + [|return base.goo;|] } } } @@ -2102,7 +2102,7 @@ public override int this[[MyPublic] int i] { get { - return base[i];$$ + [|return base[i];|] } set @@ -2392,7 +2392,7 @@ public override T this[int i] { get { - return base[i];$$ + [|return base[i];|] } set @@ -2435,7 +2435,7 @@ public override T this[int i] { get { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } set @@ -2624,7 +2624,7 @@ public override int @class { get { - return base.@class;$$ + [|return base.@class;|] } set @@ -2939,7 +2939,7 @@ public override int Goo { get { - return base.Goo;$$ + [|return base.Goo;|] } } } @@ -3594,7 +3594,7 @@ public override required int Prop { get { - return base.Prop;$$ + [|return base.Prop;|] } } } @@ -3635,7 +3635,7 @@ public override required int Prop { get { - return base.Prop;$$ + [|return base.Prop;|] } } } @@ -3676,7 +3676,7 @@ public override required int Prop { get { - return base.Prop;$$ + [|return base.Prop;|] } } } @@ -3743,7 +3743,7 @@ public override int this[int i] { get { - return base[i];$$ + [|return base[i];|] } set @@ -3885,7 +3885,7 @@ public override int goo { get { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } set diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs index 9be11ad9073a2..44b6bea63e94b 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests_ExpressionBody.cs @@ -51,7 +51,7 @@ class B public virtual int A { get; set; } class C : B { - public override int A { get => base.A$$; set => base.A = value; } + public override int A { get => [|base.A|]; set => base.A = value; } } } """; @@ -79,7 +79,7 @@ class B public virtual int A { get; } class C : B { - public override int A => base.A;$$ + public override int A => [|base.A|]; } } """; @@ -107,7 +107,7 @@ class B public virtual int A() => 2; class C : B { - public override int A() => base.A();$$ + public override int A() => [|base.A()|]; } } """; diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs index ad53c33da24ba..6b09c636c744f 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/PartialMethodCompletionProviderTests.cs @@ -417,7 +417,7 @@ partial class c partial void goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -444,7 +444,7 @@ partial class c public partial void goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -471,7 +471,7 @@ partial class c partial void goo(T bar) { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -498,7 +498,7 @@ partial class c public partial void goo(T bar) { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -525,7 +525,7 @@ partial class c partial void goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -552,7 +552,7 @@ partial class c private partial void goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -585,7 +585,7 @@ partial class c { partial void goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -618,7 +618,7 @@ partial class c { public partial void goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -645,7 +645,7 @@ partial struct c partial void goo() { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } """; @@ -744,7 +744,7 @@ partial class Bar async partial void Goo() { - throw new NotImplementedException();$$ + [|throw new NotImplementedException();|] } } """; @@ -775,7 +775,7 @@ partial class Bar public async partial void Goo() { - throw new NotImplementedException();$$ + [|throw new NotImplementedException();|] } } """; @@ -806,7 +806,7 @@ partial class Bar partial void Goo() { - throw new NotImplementedException();$$ + [|throw new NotImplementedException();|] } } """; @@ -838,7 +838,7 @@ partial class PClass partial void PMethod(int i) { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } } @@ -870,7 +870,7 @@ partial class PClass public partial void PMethod(int i) { - throw new System.NotImplementedException();$$ + [|throw new System.NotImplementedException();|] } } } @@ -903,7 +903,7 @@ partial class Bar partial class Bar { partial void Foo(); - partial void Foo() => throw new NotImplementedException();$$ + partial void Foo() => [|throw new NotImplementedException()|]; } """; @@ -936,7 +936,7 @@ partial class Bar partial class Bar { public partial void Foo(); - public partial void Foo() => throw new NotImplementedException();$$ + public partial void Foo() => [|throw new NotImplementedException()|]; } """ ; diff --git a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs index 7d4b4c67a47bc..cd0abaf590d4b 100644 --- a/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs +++ b/src/EditorFeatures/Core/IntelliSense/AsyncCompletion/CommitManager.cs @@ -278,11 +278,11 @@ private AsyncCompletionData.CommitResult Commit( updatedCurrentSnapshot = edit.Apply(); } - if (change.NewPosition.HasValue) + if (change.NewSelection.HasValue) { - // Roslyn knows how to position the caret in the snapshot we just created. - // If there were more edits made by extensions, TryMoveCaretToAndEnsureVisible maps the snapshot point to the most recent one. - view.TryMoveCaretToAndEnsureVisible(new SnapshotPoint(updatedCurrentSnapshot, change.NewPosition.Value)); + // Roslyn knows how to set the selection in the snapshot we just created. + // If there were more edits made by extensions, TrySetSelectionAndEnsureVisible maps the snapshot point to the most recent one. + view.TrySetSelectionAndEnsureVisible(new SnapshotSpan(updatedCurrentSnapshot, change.NewSelection.Value.ToSpan())); } else { diff --git a/src/EditorFeatures/Core/Shared/Extensions/ITextViewExtensions.cs b/src/EditorFeatures/Core/Shared/Extensions/ITextViewExtensions.cs index 8c5027115121d..b328be35f519c 100644 --- a/src/EditorFeatures/Core/Shared/Extensions/ITextViewExtensions.cs +++ b/src/EditorFeatures/Core/Shared/Extensions/ITextViewExtensions.cs @@ -108,6 +108,15 @@ public static void SetMultiSelection(this ITextView textView, IEnumerable textView.TryMoveCaretToAndEnsureVisible(new VirtualSnapshotPoint(point), outliningManagerService, ensureSpanVisibleOptions); diff --git a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs index 55e0869431cca..b4808de89e235 100644 --- a/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs +++ b/src/EditorFeatures/TestUtilities/Completion/AbstractCompletionProviderTests.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.AsyncCompletion; +using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -636,7 +637,7 @@ private async Task VerifyCustomCommitWorkerAsync( { using var workspaceFixture = GetOrCreateWorkspaceFixture(); - MarkupTestFile.GetPosition(expectedCodeAfterCommit, out var actualExpectedCode, out int expectedCaretPosition); + MarkupTestFile.GetPositionAndSpan(expectedCodeAfterCommit, out var actualExpectedCode, out var expectedCaretPosition, out TextSpan? expectedSelectionSpan); var options = GetCompletionOptions(); @@ -661,10 +662,15 @@ private async Task VerifyCustomCommitWorkerAsync( var textBuffer = workspaceFixture.Target.CurrentDocument.GetTextBuffer(); var actualCodeAfterCommit = textBuffer.CurrentSnapshot.AsText().ToString(); + var selectionSpan = commit.NewSelection ?? textView.Selection.StreamSelectionSpan.SnapshotSpan.Span.ToTextSpan(); var caretPosition = commit.NewPosition ?? textView.Caret.Position.BufferPosition.Position; AssertEx.EqualOrDiff(actualExpectedCode, actualCodeAfterCommit); - Assert.Equal(expectedCaretPosition, caretPosition); + + if (expectedSelectionSpan != null) + Assert.Equal(expectedSelectionSpan, selectionSpan); + else if (expectedCaretPosition != null) + Assert.Equal(expectedCaretPosition, caretPosition); } private void VerifyCustomCommitWorker( diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs index 2e61efc068f70..8ee8d2310fdef 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/CompletionUtilities.cs @@ -188,30 +188,53 @@ public static SyntaxNode GetTargetCaretPositionForMethod(BaseMethodDeclarationSy } } - public static SyntaxNode GetTargetCaretNodeForInsertedMember(SyntaxNode caretTarget) + public static TextSpan GetTargetSelectionSpanForMethod(BaseMethodDeclarationSyntax methodDeclaration) + { + if (methodDeclaration.ExpressionBody is not null) + { + // select the expression span + return methodDeclaration.ExpressionBody.Expression.Span; + } + else if (methodDeclaration.Body is not null) + { + // select the last statement in the method + return methodDeclaration.Body.Statements.Last().Span; + } + else + { + return methodDeclaration.Span; + } + } + + public static TextSpan GetTargetSelectionSpanForInsertedMember(SyntaxNode caretTarget) { switch (caretTarget) { case EventFieldDeclarationSyntax: - // Inserted Event declarations are a single line, so move to the end of the line. - return caretTarget; + // Inserted Event declarations are a single line, so move caret to the end of the line. + return new TextSpan(caretTarget.Span.End, 0); case BaseMethodDeclarationSyntax methodDeclaration: - return GetTargetCaretPositionForMethod(methodDeclaration); + return GetTargetSelectionSpanForMethod(methodDeclaration); case BasePropertyDeclarationSyntax propertyDeclaration: { - // property: no accessors; move to the end of the declaration if (propertyDeclaration.AccessorList is { Accessors: [var firstAccessor, ..] }) { - // move to the end of the last statement of the first accessor + // select the last statement of the first accessor var firstAccessorStatement = (SyntaxNode)firstAccessor.Body?.Statements.LastOrDefault() ?? firstAccessor.ExpressionBody!.Expression; - return firstAccessorStatement; + return firstAccessorStatement.Span; + } + else if (propertyDeclaration is PropertyDeclarationSyntax propertyDeclarationSyntax && propertyDeclarationSyntax.ExpressionBody.Expression is ExpressionSyntax expression) + { + // expression-bodied property: select the expression + return expression.Span; } else { - return propertyDeclaration; + // property: no accessors; move caret to the end of the declaration + return new TextSpan(propertyDeclaration.Span.End, 0); } } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs index 9312dc1603a1a..5deb7c2ba7353 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/ExplicitInterfaceMemberCompletionProvider.cs @@ -97,9 +97,9 @@ protected override SyntaxNode GetSyntax(SyntaxToken token) throw ExceptionUtilities.UnexpectedValue(token); } - protected override int GetTargetCaretPosition(SyntaxNode caretTarget) + protected override TextSpan GetTargetSelectionSpan(SyntaxNode caretTarget) { - return CompletionUtilities.GetTargetCaretNodeForInsertedMember(caretTarget).GetLocation().SourceSpan.End; + return CompletionUtilities.GetTargetSelectionSpanForInsertedMember(caretTarget); } public override async Task ProvideCompletionsAsync(CompletionContext context) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/OverrideCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/OverrideCompletionProvider.cs index 0dfefd0d30513..46c287e34f3dd 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/OverrideCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/OverrideCompletionProvider.cs @@ -204,8 +204,8 @@ public override ImmutableArray FilterOverrides(ImmutableArray return filteredMembers.Length > 0 ? filteredMembers : members; } - protected override int GetTargetCaretPosition(SyntaxNode caretTarget) + protected override TextSpan GetTargetSelectionSpan(SyntaxNode caretTarget) { - return CompletionUtilities.GetTargetCaretNodeForInsertedMember(caretTarget).GetLocation().SourceSpan.End; + return CompletionUtilities.GetTargetSelectionSpanForInsertedMember(caretTarget); } } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialMethodCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialMethodCompletionProvider.cs index 65f39e620f798..f1c6f787a9098 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialMethodCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/PartialMethodCompletionProvider.cs @@ -61,10 +61,10 @@ protected override SyntaxNode GetSyntax(SyntaxToken token) ?? throw ExceptionUtilities.UnexpectedValue(token); } - protected override int GetTargetCaretPosition(SyntaxNode caretTarget) + protected override TextSpan GetTargetSelectionSpan(SyntaxNode caretTarget) { var methodDeclaration = (MethodDeclarationSyntax)caretTarget; - return CompletionUtilities.GetTargetCaretPositionForMethod(methodDeclaration).GetLocation().SourceSpan.End; + return CompletionUtilities.GetTargetSelectionSpanForInsertedMember(methodDeclaration); } protected override SyntaxToken GetToken(CompletionItem completionItem, SyntaxTree tree, CancellationToken cancellationToken) diff --git a/src/Features/Core/Portable/Completion/CompletionChange.cs b/src/Features/Core/Portable/Completion/CompletionChange.cs index 34c86ae91789c..489acd9982f58 100644 --- a/src/Features/Core/Portable/Completion/CompletionChange.cs +++ b/src/Features/Core/Portable/Completion/CompletionChange.cs @@ -31,7 +31,13 @@ public sealed class CompletionChange /// The new caret position after the change has been applied. /// If null then the new caret position will be determined by the completion host. /// - public int? NewPosition { get; } + public int? NewPosition { get => NewSelection?.End; } + + /// + /// The new selection after the change has been applied. + /// If null then the new caret position will be determined by the completion host. + /// + internal TextSpan? NewSelection { get; } /// /// True if the changes include the typed character that caused the @@ -50,9 +56,15 @@ private CompletionChange( private CompletionChange( TextChange textChange, ImmutableArray textChanges, int? newPosition, bool includesCommitCharacter, ImmutableDictionary properties) + : this(textChange, textChanges, newPosition != null ? new TextSpan(newPosition.Value, 0) : null, includesCommitCharacter, properties) + { + } + + private CompletionChange( + TextChange textChange, ImmutableArray textChanges, TextSpan? newSelection, bool includesCommitCharacter, ImmutableDictionary properties) { TextChange = textChange; - NewPosition = newPosition; + NewSelection = newSelection; IncludesCommitCharacter = includesCommitCharacter; TextChanges = textChanges.NullToEmpty(); if (TextChanges.IsEmpty) @@ -106,6 +118,16 @@ public static CompletionChange Create( return new CompletionChange(textChange, textChanges, newPosition, includesCommitCharacter); } + internal static CompletionChange Create( + TextChange textChange, + ImmutableArray textChanges, + ImmutableDictionary properties, + TextSpan? newSpan = null, + bool includesCommitCharacter = false) + { + return new CompletionChange(textChange, textChanges, newSpan, includesCommitCharacter, properties); + } + internal static CompletionChange Create( TextChange textChange, ImmutableArray textChanges, diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs index 85ecf6aa8d684..7760cc453e3b2 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractMemberInsertingCompletionProvider.cs @@ -38,7 +38,8 @@ internal abstract partial class AbstractMemberInsertingCompletionProvider : LSPC protected abstract Task GenerateMemberAsync( Document document, CompletionItem item, Compilation compilation, ISymbol member, INamedTypeSymbol containingType, CancellationToken cancellationToken); - protected abstract int GetTargetCaretPosition(SyntaxNode caretTarget); + protected abstract TextSpan GetTargetSelectionSpan(SyntaxNode caretTarget); + protected abstract SyntaxNode GetSyntax(SyntaxToken commonSyntaxToken); protected static CompletionItemRules GetRules() @@ -46,17 +47,17 @@ protected static CompletionItemRules GetRules() public override async Task GetChangeAsync(Document document, CompletionItem item, char? commitKey = null, CancellationToken cancellationToken = default) { - var (newDocument, newPosition) = await DetermineNewDocumentAsync(document, item, cancellationToken).ConfigureAwait(false); + var (newDocument, newSpan) = await DetermineNewDocumentAsync(document, item, cancellationToken).ConfigureAwait(false); var newText = await newDocument.GetValueTextAsync(cancellationToken).ConfigureAwait(false); var changes = await newDocument.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false); var changesArray = changes.ToImmutableArray(); var change = Utilities.Collapse(newText, changesArray); - return CompletionChange.Create(change, changesArray, newPosition, includesCommitCharacter: true); + return CompletionChange.Create(change, changesArray, properties: ImmutableDictionary.Empty, newSpan, includesCommitCharacter: true); } - private async Task<(Document, int? caretPosition)> DetermineNewDocumentAsync( + private async Task<(Document, TextSpan? caretPosition)> DetermineNewDocumentAsync( Document document, CompletionItem completionItem, CancellationToken cancellationToken) @@ -168,7 +169,7 @@ private TextSpan ComputeDestinationSpan(SyntaxNode insertionRoot) return TextSpan.FromBounds(startToken.Value.SpanStart, line.EndIncludingLineBreak); } - private async Task<(Document Document, int? CaretPosition)> RemoveDestinationNodeAsync( + private async Task<(Document Document, TextSpan? Selection)> RemoveDestinationNodeAsync( Document memberContainingDocument, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken) { // We now have a replacement node inserted into the document, but we still have the source code that triggered completion (with associated trivia). @@ -228,18 +229,18 @@ private TextSpan ComputeDestinationSpan(SyntaxNode insertionRoot) var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); // We have basically the final tree. Calculate the new caret position while we still have the annotations. - int? caretPosition = null; + TextSpan? newSpan = null; var caretTarget = root.GetAnnotatedNodes(_annotation).FirstOrDefault(); if (caretTarget != null) { - var targetPosition = GetTargetCaretPosition(caretTarget); + var targetSelectionSpan = GetTargetSelectionSpan(caretTarget); - if (targetPosition > 0 && targetPosition <= text.Length) + if (targetSelectionSpan.Start > 0 && targetSelectionSpan.End <= text.Length) { // The new replacement method should always be inserted before the destination span we're removing. - // This means the caret position in the inserted method should be safe to return as-is. - Debug.Assert(targetPosition < destinationSpan.Start); - caretPosition = targetPosition; + // This means the end selection position in the inserted method should be safe to return as-is. + Debug.Assert(targetSelectionSpan.End < destinationSpan.Start); + newSpan = targetSelectionSpan; } } @@ -249,7 +250,7 @@ private TextSpan ComputeDestinationSpan(SyntaxNode insertionRoot) var textChange = new TextChange(text.Lines[lineNumber].SpanIncludingLineBreak, string.Empty); text = text.WithChanges(textChange); - return (document.WithText(text), caretPosition); + return (document.WithText(text), newSpan); } internal override Task GetDescriptionWorkerAsync(Document document, CompletionItem item, CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken) diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/OverrideCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/OverrideCompletionProvider.vb index d57901b07dd5a..0214f41b3aa66 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/OverrideCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/OverrideCompletionProvider.vb @@ -197,20 +197,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Return False End Function - Protected Overrides Function GetTargetCaretPosition(caretTarget As SyntaxNode) As Integer + Protected Overrides Function GetTargetSelectionSpan(caretTarget As SyntaxNode) As TextSpan Dim node = DirectCast(caretTarget, SyntaxNode) ' MustOverride Sub | MustOverride Function: move to end of line Dim methodStatement = TryCast(node, MethodStatementSyntax) If methodStatement IsNot Nothing Then - Return methodStatement.GetLocation().SourceSpan.End + Return New TextSpan(methodStatement.GetLocation().SourceSpan.End, 0) End If Dim methodBlock = TryCast(node, MethodBlockBaseSyntax) If methodBlock IsNot Nothing Then Dim lastStatement = methodBlock.Statements.LastOrDefault() If lastStatement IsNot Nothing Then - Return lastStatement.GetLocation().SourceSpan.End + Return New TextSpan(lastStatement.GetLocation().SourceSpan.End, 0) End If End If @@ -220,12 +220,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers If firstAccessor IsNot Nothing Then Dim lastAccessorStatement = firstAccessor.Statements.LastOrDefault() If lastAccessorStatement IsNot Nothing Then - Return lastAccessorStatement.GetLocation().SourceSpan.End + Return New TextSpan(lastAccessorStatement.GetLocation().SourceSpan.End, 0) End If End If End If - Return -1 + Return New TextSpan(0, 0) End Function End Class End Namespace