예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
 private void AddToReferencesToReport_MustBeCalledUnderLock(VSReferenceItem item)
 {
     Debug.Assert(_semaphore.CurrentCount == 0);
     _resultsChunk.Add(item);
 }
예제 #4
0
        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]);
                }
            }
        }
예제 #5
0
 private bool AssertVSReferenceItem(VSReferenceItem expected, VSReferenceItem actual)
 {
     Assert.Equal(expected.Location, actual.Location);
     Assert.Equal(expected.DisplayPath, actual.DisplayPath);
     return(true);
 }