From d10df884adf65801757bb7179baa39befbaa529e Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Mon, 29 Mar 2021 18:48:09 -0700 Subject: [PATCH] Fix caret affinity in GetReferencedSymbolsToLeftOfCaretAsync --- .../AbstractSnippetExpansionClient.cs | 8 +++++- .../CSharp/CSharpArgumentProvider.cs | 28 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs b/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs index f1243358170a..cfdedb05443b 100644 --- a/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs +++ b/src/VisualStudio/Core/Def/Implementation/Snippets/AbstractSnippetExpansionClient.cs @@ -722,7 +722,13 @@ private static async Task> GetReferencedSymbolsToLeftOfC CancellationToken cancellationToken) { var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var token = await semanticModel.SyntaxTree.GetTouchingTokenAsync(caretPosition.Position, cancellationToken).ConfigureAwait(false); + + // GetTouchingTokenAsync prefers to return tokens to the right of the caret. Adjust the caret position one + // to the left to avoid this. + if (caretPosition.Position == 0) + return ImmutableArray.Empty; + + var token = await semanticModel.SyntaxTree.GetTouchingTokenAsync(caretPosition.Position - 1, cancellationToken).ConfigureAwait(false); var semanticInfo = semanticModel.GetSemanticInfo(token, document.Project.Solution.Workspace, cancellationToken); return semanticInfo.ReferencedSymbols; } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpArgumentProvider.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpArgumentProvider.cs index 705cb6177076..ee83de3f8aae 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpArgumentProvider.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpArgumentProvider.cs @@ -57,6 +57,34 @@ public void Method() VisualStudio.Editor.Verify.CurrentLineText("f.ToString()$$", assertCaretPosition: true); } + [WpfFact] + public void TabTabBeforeSemicolon() + { + SetUpEditor(@" +public class Test +{ + private object f; + + public void Method() + { + $$; + } +} +"); + + VisualStudio.Editor.SendKeys("f.ToSt"); + + VisualStudio.Editor.SendKeys(VirtualKey.Tab); + VisualStudio.Editor.Verify.CurrentLineText("f.ToString$$;", assertCaretPosition: true); + + VisualStudio.Editor.SendKeys(VirtualKey.Tab); + VisualStudio.Workspace.WaitForAllAsyncOperations(Helper.HangMitigatingTimeout, FeatureAttribute.SignatureHelp); + VisualStudio.Editor.Verify.CurrentLineText("f.ToString($$);", assertCaretPosition: true); + + VisualStudio.Editor.SendKeys(VirtualKey.Tab); + VisualStudio.Editor.Verify.CurrentLineText("f.ToString()$$;", assertCaretPosition: true); + } + [WpfFact] public void TabTabCompletionWithArguments() {