From e76f120343eb3660c0b2231fabbdec111ff231f1 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 25 Jul 2024 16:48:53 -0700 Subject: [PATCH 1/5] Add LSP far many references tests --- .../FindAllReferencesHandlerFeaturesTests.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs b/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs index d0b34c6580445..c93dbc2b7dbb2 100644 --- a/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs +++ b/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using System.Linq; +using System.ServiceModel.Syndication; using System.Threading.Tasks; +using EnvDTE; using Microsoft.CodeAnalysis.Editor.Test; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -47,4 +49,36 @@ void M2() var results = await FindAllReferencesHandlerTests.RunFindAllReferencesNonVSAsync(testLspServer, testLspServer.GetLocations("caret").First()); AssertLocationsEqual(testLspServer.GetLocations("reference"), results.Select(result => result)); } + + [Theory, CombinatorialData] + public async Task TestFindAllReferencesAsync_LargeNumberOfReferences(bool mutatingLspWorkspace, [CombinatorialRange(0, 50)] int iteration) + { + _ = iteration; + var markup = +@"using System.Threading.Tasks +class A +{ + private {|caret:Task|} someTask = Task.CompletedTask; +}"; + await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, new LSP.ClientCapabilities()); + + for (var i = 0; i < 100; i++) + { + var source = $$""" + using System.Threading.Tasks + class SomeClass{{i}} + { + private Task someTask; + } + """; + + var testDocument = new EditorTestHostDocument(text: source, displayName: @$"C:\SomeFile{i}.cs", exportProvider: testLspServer.TestWorkspace.ExportProvider, filePath: @$"C:\SomeFile{i}.cs"); + testLspServer.TestWorkspace.AddTestProject(new EditorTestHostProject(testLspServer.TestWorkspace, documents: new[] { testDocument })); + } + + await WaitForWorkspaceOperationsAsync(testLspServer.TestWorkspace); + + var results = await FindAllReferencesHandlerTests.RunFindAllReferencesNonVSAsync(testLspServer, testLspServer.GetLocations("caret").First()); + Assert.Equal(103, results.Length); + } } From bce3670cf4dd81fc48ff94d792ced7c8266e048a Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 25 Jul 2024 17:11:38 -0700 Subject: [PATCH 2/5] Add linked file FAR test --- .../FindAllReferencesHandlerFeaturesTests.cs | 82 ++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs b/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs index c93dbc2b7dbb2..30b6bd074915d 100644 --- a/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs +++ b/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs @@ -51,9 +51,8 @@ void M2() } [Theory, CombinatorialData] - public async Task TestFindAllReferencesAsync_LargeNumberOfReferences(bool mutatingLspWorkspace, [CombinatorialRange(0, 50)] int iteration) + public async Task TestFindAllReferencesAsync_LargeNumberOfReferences(bool mutatingLspWorkspace) { - _ = iteration; var markup = @"using System.Threading.Tasks class A @@ -81,4 +80,83 @@ class SomeClass{{i}} var results = await FindAllReferencesHandlerTests.RunFindAllReferencesNonVSAsync(testLspServer, testLspServer.GetLocations("caret").First()); Assert.Equal(103, results.Length); } + + [Theory, CombinatorialData] + public async Task TestFindAllReferencesAsync_LinkedFile(bool mutatingLspWorkspace, [CombinatorialRange(0, 10)] int iteration) + { + _ = iteration; + var markup = +@"using System.Threading.Tasks +class A +{ + private void SomeMethod() + { + Do({|caret:Task|}.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + } +}"; + + var workspaceXml = +$@" + + {markup} + + + + +"; + + await using var testLspServer = await CreateXmlTestLspServerAsync(workspaceXml, mutatingLspWorkspace, initializationOptions: new InitializationOptions + { + ClientCapabilities = new LSP.ClientCapabilities() + }); + + await WaitForWorkspaceOperationsAsync(testLspServer.TestWorkspace); + + var results = await FindAllReferencesHandlerTests.RunFindAllReferencesNonVSAsync(testLspServer, testLspServer.GetLocations("caret").First()); + Assert.Equal(46, results.Length); + } } From 96b5350981abdcdb064acd73cb3e6a52ae70f70c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 26 Jul 2024 10:59:09 -0700 Subject: [PATCH 3/5] Fix early exist in loop --- .../Protocol/Handler/References/FindUsagesLSPContext.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs b/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs index 92c7cec421960..35d1738000687 100644 --- a/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs +++ b/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs @@ -132,6 +132,9 @@ public override async ValueTask OnDefinitionFoundAsync(DefinitionItem definition public override async ValueTask OnReferencesFoundAsync(IAsyncEnumerable references, CancellationToken cancellationToken) { await foreach (var reference in references) + await OnSingleReferenceFoundAsync(reference, cancellationToken).ConfigureAwait(false); + + async ValueTask OnSingleReferenceFoundAsync(SourceReferenceItem reference, CancellationToken cancellationToken) { using (await _semaphore.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { From ceece591049ac41b14ba8d70c856afa88158ad92 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 26 Jul 2024 11:01:41 -0700 Subject: [PATCH 4/5] Inline' gitpush --- .../Protocol/Handler/References/FindUsagesLSPContext.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs b/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs index 35d1738000687..a9fa355459e8c 100644 --- a/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs +++ b/src/LanguageServer/Protocol/Handler/References/FindUsagesLSPContext.cs @@ -132,16 +132,13 @@ public override async ValueTask OnDefinitionFoundAsync(DefinitionItem definition public override async ValueTask OnReferencesFoundAsync(IAsyncEnumerable references, CancellationToken cancellationToken) { await foreach (var reference in references) - await OnSingleReferenceFoundAsync(reference, cancellationToken).ConfigureAwait(false); - - async ValueTask OnSingleReferenceFoundAsync(SourceReferenceItem reference, CancellationToken cancellationToken) { using (await _semaphore.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { // Each reference should be associated with a definition. If this somehow isn't the // case, we bail out early. if (!_definitionToId.TryGetValue(reference.Definition, out var definitionId)) - return; + continue; var documentSpan = reference.SourceSpan; var document = documentSpan.Document; @@ -149,7 +146,7 @@ async ValueTask OnSingleReferenceFoundAsync(SourceReferenceItem reference, Cance // If this is reference to the same physical location we've already reported, just // filter this out. it will clutter the UI to show the same places. if (!_referenceLocations.Add((document.FilePath, reference.SourceSpan.SourceSpan))) - return; + continue; // If the definition hasn't been reported yet, add it to our list of references to report. if (_definitionsWithoutReference.TryGetValue(definitionId, out var definition)) From 88c618cfd018fefffa14ea9e872c50ace81c7ba1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 26 Jul 2024 11:02:55 -0700 Subject: [PATCH 5/5] Update tests' --- .../FindAllReferencesHandlerFeaturesTests.cs | 179 +++++++++--------- 1 file changed, 91 insertions(+), 88 deletions(-) diff --git a/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs b/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs index 30b6bd074915d..cd0c9aee888bb 100644 --- a/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs +++ b/src/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerFeaturesTests.cs @@ -3,9 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Linq; -using System.ServiceModel.Syndication; using System.Threading.Tasks; -using EnvDTE; using Microsoft.CodeAnalysis.Editor.Test; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -14,12 +12,9 @@ using LSP = Roslyn.LanguageServer.Protocol; namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.References; -public class FindAllReferencesHandlerFeaturesTests : AbstractLanguageServerProtocolTests +public sealed class FindAllReferencesHandlerFeaturesTests(ITestOutputHelper? testOutputHelper) + : AbstractLanguageServerProtocolTests(testOutputHelper) { - public FindAllReferencesHandlerFeaturesTests(ITestOutputHelper? testOutputHelper) : base(testOutputHelper) - { - } - protected override TestComposition Composition => LspTestCompositions.LanguageServerProtocol .AddParts(typeof(TestDocumentTrackingService)) .AddParts(typeof(TestWorkspaceRegistrationService)); @@ -28,22 +23,24 @@ public FindAllReferencesHandlerFeaturesTests(ITestOutputHelper? testOutputHelper public async Task TestFindAllReferencesAsync_DoesNotUseVSTypes(bool mutatingLspWorkspace) { var markup = -@"class A -{ - public int {|reference:someInt|} = 1; - void M() - { - var i = {|reference:someInt|} + 1; - } -} -class B -{ - int someInt = A.{|reference:someInt|} + 1; - void M2() - { - var j = someInt + A.{|caret:|}{|reference:someInt|}; - } -}"; + """ + class A + { + public int {|reference:someInt|} = 1; + void M() + { + var i = {|reference:someInt|} + 1; + } + } + class B + { + int someInt = A.{|reference:someInt|} + 1; + void M2() + { + var j = someInt + A.{|caret:|}{|reference:someInt|}; + } + } + """; await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, new LSP.ClientCapabilities()); var results = await FindAllReferencesHandlerTests.RunFindAllReferencesNonVSAsync(testLspServer, testLspServer.GetLocations("caret").First()); @@ -54,11 +51,13 @@ void M2() public async Task TestFindAllReferencesAsync_LargeNumberOfReferences(bool mutatingLspWorkspace) { var markup = -@"using System.Threading.Tasks -class A -{ - private {|caret:Task|} someTask = Task.CompletedTask; -}"; + """ + using System.Threading.Tasks + class A + { + private {|caret:Task|} someTask = Task.CompletedTask; + } + """; await using var testLspServer = await CreateTestLspServerAsync(markup, mutatingLspWorkspace, new LSP.ClientCapabilities()); for (var i = 0; i < 100; i++) @@ -86,68 +85,72 @@ public async Task TestFindAllReferencesAsync_LinkedFile(bool mutatingLspWorkspac { _ = iteration; var markup = -@"using System.Threading.Tasks -class A -{ - private void SomeMethod() - { - Do({|caret:Task|}.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - Do(Task.CompletedTask); - } -}"; + """ + using System.Threading.Tasks + class A + { + private void SomeMethod() + { + Do({|caret:Task|}.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + Do(Task.CompletedTask); + } + } + """; var workspaceXml = -$@" - - {markup} - - - - -"; + $""" + + + {markup} + + + + + + """; await using var testLspServer = await CreateXmlTestLspServerAsync(workspaceXml, mutatingLspWorkspace, initializationOptions: new InitializationOptions {