Exemplo n.º 1
0
        private void StreamingGoToImplementation(
            Document document, int caretPosition,
            IFindUsagesService findUsagesService,
            IStreamingFindUsagesPresenter streamingPresenter,
            CancellationToken cancellationToken,
            out string messageToShow)
        {
            // We create our own context object, simply to capture all the definitions reported by
            // the individual IFindUsagesService.  Once we get the results back we'll then decide
            // what to do with them.  If we get only a single result back, then we'll just go
            // directly to it.  Otherwise, we'll present the results in the IStreamingFindUsagesPresenter.
            var goToImplContext = new SimpleFindUsagesContext(cancellationToken);

            findUsagesService.FindImplementationsAsync(document, caretPosition, goToImplContext).Wait(cancellationToken);

            // If finding implementations reported a message, then just stop and show that
            // message to the user.
            messageToShow = goToImplContext.Message;
            if (messageToShow != null)
            {
                return;
            }

            var definitionItems = goToImplContext.GetDefinitions();

            streamingPresenter.TryNavigateToOrPresentItemsAsync(
                goToImplContext.SearchTitle, definitionItems,
                alwaysShowDeclarations: true).Wait(cancellationToken);
        }
Exemplo n.º 2
0
        public async Task <object[]> HandleAsync(LSP.ReferenceParams request, RequestContext <Solution> requestContext, CancellationToken cancellationToken)
        {
            var locations = ArrayBuilder <LSP.Location> .GetInstance();

            var solution = requestContext.Context;
            var document = solution.GetDocumentFromURI(request.TextDocument.Uri);

            if (document == null)
            {
                return(locations.ToArrayAndFree());
            }

            var findUsagesService = document.Project.LanguageServices.GetService <IFindUsagesService>();
            var position          = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            var context = new SimpleFindUsagesContext(cancellationToken);

            // Roslyn calls into third party extensions to compute reference results and needs to be on the UI thread to compute results.
            // This is not great for us and ideally we should ask for a Roslyn API where we can make this call without blocking the UI.
            if (VsTaskLibraryHelper.ServiceInstance != null)
            {
                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
            }

            await findUsagesService.FindReferencesAsync(document, position, context).ConfigureAwait(false);

            if (requestContext?.ClientCapabilities?.HasVisualStudioLspCapability() == true)
            {
                return(await GetReferenceGroupsAsync(request, context, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                return(await GetLocationsAsync(request, context, cancellationToken).ConfigureAwait(false));
            }
        }
Exemplo n.º 3
0
        private void StreamingGoTo(
            Document document, int caretPosition,
            TLanguageService service,
            IStreamingFindUsagesPresenter streamingPresenter,
            CancellationToken cancellationToken,
            out string messageToShow)
        {
            // We create our own context object, simply to capture all the definitions reported by
            // the individual TLanguageService.  Once we get the results back we'll then decide
            // what to do with them.  If we get only a single result back, then we'll just go
            // directly to it.  Otherwise, we'll present the results in the IStreamingFindUsagesPresenter.
            var context = new SimpleFindUsagesContext(cancellationToken);

            FindActionAsync(service, document, caretPosition, context).Wait(cancellationToken);

            // If FindAction reported a message, then just stop and show that
            // message to the user.
            messageToShow = context.Message;
            if (messageToShow != null)
            {
                return;
            }

            var definitionItems = context.GetDefinitions();

            streamingPresenter.TryNavigateToOrPresentItemsAsync(
                document.Project.Solution.Workspace, context.SearchTitle, definitionItems).Wait(cancellationToken);
        }
Exemplo n.º 4
0
        /// <summary>
        ///  Using the find usages service is more expensive than using the definitions service because a lot of unnecessary information is computed. However, some languages
        /// don't provide an <see cref="IGoToDefinitionService"/> implementation that will return definitions so we must use <see cref="IFindUsagesService"/>.
        /// </summary>
        private async Task <List <LSP.Location> > GetDefinitionsWithFindUsagesService(Document document, int pos, CancellationToken cancellationToken)
        {
            var findUsagesService = document.Project.LanguageServices.GetService <IFindUsagesService>();

            var context = new SimpleFindUsagesContext(cancellationToken);

            // Roslyn calls into third party extensions to compute reference results and needs to be on the UI thread to compute results.
            // This is not great for us and ideally we should ask for a Roslyn API where we can make this call without blocking the UI.
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            await findUsagesService.FindReferencesAsync(document, pos, context).ConfigureAwait(false);

            var locations = new List <LSP.Location>();

            var definitions = context.GetDefinitions();

            if (definitions != null)
            {
                foreach (var definition in definitions)
                {
                    foreach (var docSpan in definition.SourceSpans)
                    {
                        locations.Add(await ProtocolConversions.DocumentSpanToLocationAsync(docSpan, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(locations);
        }
Exemplo n.º 5
0
        public override async Task <LSP.Location[]> HandleRequestAsync(LSP.TextDocumentPositionParams request, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

            Contract.ThrowIfNull(document);

            var locations = ArrayBuilder <LSP.Location> .GetInstance();

            var findUsagesService = document.GetRequiredLanguageService <IFindUsagesService>();
            var position          = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            var findUsagesContext = new SimpleFindUsagesContext();

            await FindImplementationsAsync(findUsagesService, document, position, findUsagesContext, cancellationToken).ConfigureAwait(false);

            foreach (var definition in findUsagesContext.GetDefinitions())
            {
                var text = definition.GetClassifiedText();
                foreach (var sourceSpan in definition.SourceSpans)
                {
                    if (context.ClientCapabilities?.HasVisualStudioLspCapability() == true)
                    {
                        locations.AddIfNotNull(await ProtocolConversions.DocumentSpanToLocationWithTextAsync(sourceSpan, text, cancellationToken).ConfigureAwait(false));
                    }
                    else
                    {
                        locations.AddIfNotNull(await ProtocolConversions.DocumentSpanToLocationAsync(sourceSpan, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(locations.ToArrayAndFree());
        }
Exemplo n.º 6
0
        private async Task <string> NavigateToOrPresentResultsAsync(
            Document document,
            int caretPosition,
            TLanguageService service,
            CancellationToken cancellationToken
            )
        {
            // We create our own context object, simply to capture all the definitions reported by
            // the individual TLanguageService.  Once we get the results back we'll then decide
            // what to do with them.  If we get only a single result back, then we'll just go
            // directly to it.  Otherwise, we'll present the results in the IStreamingFindUsagesPresenter.
            var context = new SimpleFindUsagesContext(cancellationToken);

            await FindActionAsync(service, document, caretPosition, context).ConfigureAwait(false);

            if (context.Message != null)
            {
                return(context.Message);
            }

            await _streamingPresenter
            .TryNavigateToOrPresentItemsAsync(
                _threadingContext,
                document.Project.Solution.Workspace,
                context.SearchTitle,
                context.GetDefinitions(),
                cancellationToken
                )
            .ConfigureAwait(false);

            return(null);
        }
        public async Task <object> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
                                                      LSP.ClientCapabilities clientCapabilities, CancellationToken cancellationToken)
        {
            var locations = ArrayBuilder <LSP.Location> .GetInstance();

            var document = solution.GetDocumentFromURI(request.TextDocument.Uri);

            if (document == null)
            {
                return(locations.ToArrayAndFree());
            }

            var findUsagesService = document.Project.LanguageServices.GetService <IFindUsagesService>();
            var position          = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            var context = new SimpleFindUsagesContext(cancellationToken);

            await FindImplementationsAsync(findUsagesService, document, position, context).ConfigureAwait(false);

            foreach (var definition in context.GetDefinitions())
            {
                var text = definition.GetClassifiedText();
                foreach (var sourceSpan in context.GetDefinitions().SelectMany(definition => definition.SourceSpans))
                {
                    if (clientCapabilities?.HasVisualStudioLspCapability() == true)
                    {
                        locations.Add(await ProtocolConversions.DocumentSpanToLocationWithTextAsync(sourceSpan, text, cancellationToken).ConfigureAwait(false));
                    }
                    else
                    {
                        locations.Add(await ProtocolConversions.DocumentSpanToLocationAsync(sourceSpan, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            return(locations.ToArrayAndFree());
        }
Exemplo n.º 8
0
        private async Task <LSP.ReferenceGroup[]> GetReferenceGroupsAsync(LSP.ReferenceParams request, SimpleFindUsagesContext context, CancellationToken cancellationToken)
        {
            var definitionMap = new Dictionary <DefinitionItem, List <SourceReferenceItem> >();

            foreach (var reference in context.GetReferences())
            {
                if (!definitionMap.ContainsKey(reference.Definition))
                {
                    definitionMap.Add(reference.Definition, new List <SourceReferenceItem>());
                }

                definitionMap[reference.Definition].Add(reference);
            }

            var referenceGroups = ArrayBuilder <LSP.ReferenceGroup> .GetInstance();

            foreach (var keyValuePair in definitionMap)
            {
                var definition = keyValuePair.Key;
                var references = keyValuePair.Value;

                var referenceGroup = new LSP.ReferenceGroup();
                var text           = definition.GetClassifiedText();

                referenceGroup.Definition = await ProtocolConversions.DocumentSpanToLocationWithTextAsync(definition.SourceSpans.First(), text, cancellationToken).ConfigureAwait(false);

                referenceGroup.DefinitionIcon = new ImageElement(definition.Tags.GetFirstGlyph().GetImageId());

                var locationWithTexts = new ArrayBuilder <LSP.LocationWithText>();
                foreach (var reference in references)
                {
                    var classifiedSpansAndHighlightSpan = await ClassifiedSpansAndHighlightSpanFactory.ClassifyAsync(reference.SourceSpan, context.CancellationToken).ConfigureAwait(false);

                    var classifiedSpans   = classifiedSpansAndHighlightSpan.ClassifiedSpans;
                    var referenceLocation = await ProtocolConversions.DocumentSpanToLocationAsync(reference.SourceSpan, cancellationToken).ConfigureAwait(false);

                    var docText = await reference.SourceSpan.Document.GetTextAsync(context.CancellationToken).ConfigureAwait(false);

                    var classifiedText   = new ClassifiedTextElement(classifiedSpans.Select(cspan => new ClassifiedTextRun(cspan.ClassificationType, docText.ToString(cspan.TextSpan))));
                    var locationWithText = new LSP.LocationWithText {
                        Range = referenceLocation.Range, Uri = referenceLocation.Uri, Text = classifiedText
                    };
                    locationWithTexts.Add(locationWithText);
                }

                referenceGroup.References = locationWithTexts.ToArrayAndFree();
                referenceGroups.Add(referenceGroup);
            }

            return(referenceGroups.ToArrayAndFree());
        }
Exemplo n.º 9
0
        private static async Task <LSP.Location[]> GetLocationsAsync(LSP.ReferenceParams request, SimpleFindUsagesContext context, CancellationToken cancellationToken)
        {
            var locations = ArrayBuilder <LSP.Location> .GetInstance();

            if (request.Context.IncludeDeclaration)
            {
                foreach (var definition in context.GetDefinitions())
                {
                    foreach (var docSpan in definition.SourceSpans)
                    {
                        locations.Add(await ProtocolConversions.DocumentSpanToLocationAsync(docSpan, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            foreach (var reference in context.GetReferences())
            {
                locations.Add(await ProtocolConversions.DocumentSpanToLocationAsync(reference.SourceSpan, cancellationToken).ConfigureAwait(false));
            }

            return(locations.ToArrayAndFree());
        }
Exemplo n.º 10
0
        protected override async Task FindImplementationsAsync(IFindUsagesService findUsagesService, Document document, int position, SimpleFindUsagesContext context)
        {
            // TypeScript expects to be called on the UI to get implementations.
            await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(context.CancellationToken);

            await base.FindImplementationsAsync(findUsagesService, document, position, context).ConfigureAwait(false);
        }
 protected virtual Task FindImplementationsAsync(IFindUsagesService findUsagesService, Document document, int position, SimpleFindUsagesContext context)
 => findUsagesService.FindImplementationsAsync(document, position, context);
Exemplo n.º 12
0
 protected virtual Task FindImplementationsAsync(IFindUsagesServiceRenameOnceTypeScriptMovesToExternalAccess findUsagesService, Document document, int position, SimpleFindUsagesContext context)
 => findUsagesService.FindImplementationsAsync(document, position, context);