private (LSPRequestInvoker, LSPProgressListener) MockServices(VSReferenceItem csharpLocation, out string token) { var languageServiceBroker = Mock.Of <ILanguageServiceBroker2>(); var lspProgressListener = new DefaultLSPProgressListener(languageServiceBroker); var requestInvoker = new Mock <LSPRequestInvoker>(); token = Guid.NewGuid().ToString(); var parameterToken = new JObject { { "token", token }, { "value", JArray.FromObject(new[] { csharpLocation }) } }; requestInvoker.Setup(i => i.ReinvokeRequestOnServerAsync <TextDocumentPositionParams, VSReferenceItem[]>( It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TextDocumentPositionParams>(), It.IsAny <CancellationToken>())) .Callback <string, string, TextDocumentPositionParams, CancellationToken>((method, serverContentType, definitionParams, ct) => { Assert.Equal(Methods.TextDocumentReferencesName, method); Assert.Equal(RazorLSPConstants.CSharpContentTypeName, serverContentType); _ = lspProgressListener.ProcessProgressNotificationAsync(Methods.ProgressNotificationName, parameterToken); }) .Returns(Task.FromResult(Array.Empty <VSReferenceItem>())); return(requestInvoker.Object, lspProgressListener); }
private bool AssertVSReferenceItem(VSReferenceItem expected, VSReferenceItem actual) { Assert.Equal(expected.Location, actual.Location); Assert.Equal(expected.DisplayPath, actual.DisplayPath); if (actual.Text is string) { Assert.Equal(expected.Text, actual.Text); Assert.Equal(expected.DefinitionText, actual.DefinitionText); } else { Assert.Equal( expected.Text as ClassifiedTextElement, actual.Text as ClassifiedTextElement, ClassifiedTextElementComparer.Default); Assert.Equal( expected.DefinitionText as ClassifiedTextElement, actual.DefinitionText as ClassifiedTextElement, ClassifiedTextElementComparer.Default); } return(true); }
private void AddToReferencesToReport_MustBeCalledUnderLock(VSReferenceItem item) { Debug.Assert(_semaphore.CurrentCount == 0); _resultsChunk.Add(item); }
public async Task HandleRequestAsync_LargeProject_InvokesCSharpLanguageServer() { // Validates batching mechanism for the progress notification on large projects // Arrange var lspFarEndpointCalled = false; const int BATCH_SIZE = 10; const int NUM_BATCHES = 10; const int NUM_DOCUMENTS = BATCH_SIZE * NUM_BATCHES; const int MAPPING_OFFSET = 10; var expectedUris = new Uri[NUM_DOCUMENTS]; var virtualUris = new Uri[NUM_DOCUMENTS]; var expectedReferences = new VSReferenceItem[NUM_BATCHES][]; var csharpUnmappedReferences = new VSReferenceItem[NUM_BATCHES][]; var parameterTokens = new JObject[NUM_BATCHES]; var token = Guid.NewGuid().ToString(); var documentNumber = 0; for (var batch = 0; batch < NUM_BATCHES; ++batch) { expectedReferences[batch] = new VSReferenceItem[BATCH_SIZE]; csharpUnmappedReferences[batch] = new VSReferenceItem[BATCH_SIZE]; for (var documentInBatch = 0; documentInBatch < BATCH_SIZE; ++documentInBatch) { expectedUris[documentNumber] = new Uri($"C:/path/to/file{documentNumber}.razor"); virtualUris[documentNumber] = new Uri($"C:/path/to/file{documentNumber}.razor.g.cs"); expectedReferences[batch][documentInBatch] = GetReferenceItem(documentNumber, expectedUris[documentNumber]); var umappedOffset = documentNumber * MAPPING_OFFSET; csharpUnmappedReferences[batch][documentInBatch] = GetReferenceItem(umappedOffset, virtualUris[documentNumber]); documentNumber++; } parameterTokens[batch] = new JObject { { "token", token }, { "value", JArray.FromObject(csharpUnmappedReferences[batch]) } }; } var documentManager = new TestDocumentManager(); documentManager.AddDocument(Uri, Mock.Of <LSPDocumentSnapshot>()); var languageServiceBroker = Mock.Of <ILanguageServiceBroker2>(); using var lspProgressListener = new DefaultLSPProgressListener(languageServiceBroker); var requestInvoker = new Mock <LSPRequestInvoker>(); requestInvoker .Setup(r => r.ReinvokeRequestOnServerAsync <TextDocumentPositionParams, VSReferenceItem[]>(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TextDocumentPositionParams>(), It.IsAny <CancellationToken>())) .Callback <string, string, TextDocumentPositionParams, CancellationToken>((method, serverContentType, definitionParams, ct) => { Assert.Equal(Methods.TextDocumentReferencesName, method); Assert.Equal(RazorLSPConstants.CSharpContentTypeName, serverContentType); lspFarEndpointCalled = true; for (var i = 0; i < NUM_BATCHES; ++i) { _ = lspProgressListener.ProcessProgressNotificationAsync(Methods.ProgressNotificationName, parameterTokens[i]); } }) .Returns(Task.FromResult(Array.Empty <VSReferenceItem>())); var projectionResult = new ProjectionResult() { LanguageKind = RazorLanguageKind.CSharp, }; var projectionProvider = new Mock <LSPProjectionProvider>(); projectionProvider.Setup(p => p.GetProjectionAsync(It.IsAny <LSPDocumentSnapshot>(), It.IsAny <Position>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(projectionResult)); var documentMappingProvider = new Mock <LSPDocumentMappingProvider>(); documentMappingProvider .Setup(d => d.MapToDocumentRangesAsync(RazorLanguageKind.CSharp, It.IsAny <Uri>(), It.IsAny <Range[]>(), It.IsAny <CancellationToken>())) .Returns <RazorLanguageKind, Uri, Range[], CancellationToken>((languageKind, uri, ranges, ct) => { var unmappedPosition = ranges[0].Start.Line; var mappedPosition = unmappedPosition / MAPPING_OFFSET; var mappedRange = new Range() { Start = new Position(mappedPosition, mappedPosition), End = new Position(mappedPosition, mappedPosition) }; var response = new RazorMapToDocumentRangesResponse() { Ranges = new[] { mappedRange } }; return(Task.FromResult(response)); }); var referencesHandler = new FindAllReferencesHandler(requestInvoker.Object, documentManager, projectionProvider.Object, documentMappingProvider.Object, lspProgressListener); referencesHandler.WaitForProgressNotificationTimeout = TestWaitForProgressNotificationTimeout; var progressBatchesReported = new ConcurrentBag <VSReferenceItem[]>(); var progressToken = new ProgressWithCompletion <object>((val) => { var results = Assert.IsType <VSReferenceItem[]>(val); Assert.Equal(BATCH_SIZE, results.Length); progressBatchesReported.Add(results); }); var referenceRequest = new ReferenceParams() { TextDocument = new TextDocumentIdentifier() { Uri = Uri }, Position = new Position(10, 5), PartialResultToken = progressToken }; // Act var result = await referencesHandler.HandleRequestAsync(referenceRequest, new ClientCapabilities(), token, CancellationToken.None).ConfigureAwait(false); // Assert Assert.True(lspFarEndpointCalled); var sortedBatchesReported = progressBatchesReported.ToList(); sortedBatchesReported.Sort((VSReferenceItem[] a, VSReferenceItem[] b) => { var indexA = a[0].Location.Range.Start.Character; var indexB = b[0].Location.Range.Start.Character; return(indexA.CompareTo(indexB)); }); Assert.Equal(NUM_BATCHES, sortedBatchesReported.Count); for (var batch = 0; batch < NUM_BATCHES; ++batch) { for (var documentInBatch = 0; documentInBatch < BATCH_SIZE; ++documentInBatch) { AssertVSReferenceItem( expectedReferences[batch][documentInBatch], sortedBatchesReported[batch][documentInBatch]); } } }
private bool AssertVSReferenceItem(VSReferenceItem expected, VSReferenceItem actual) { Assert.Equal(expected.Location, actual.Location); Assert.Equal(expected.DisplayPath, actual.DisplayPath); return(true); }