private static ImmutableArray <DefinitionItem> GetIncludeDefinitionItem(LogicalDocument document, SyntaxToken syntaxToken)
        {
            var includeDirective = (IncludeDirectiveTriviaSyntax)syntaxToken.Parent;

            var syntaxTree = document.GetSyntaxTreeSynchronously(CancellationToken.None);

            var workspace = document.Workspace;

            var includeFileSystem = workspace.Services.GetRequiredService <IWorkspaceIncludeFileSystem>();

            var parseOptions        = (HlslParseOptions)syntaxTree.Options;
            var includeFileResolver = new IncludeFileResolver(includeFileSystem, parseOptions);

            var currentFile = ((SyntaxTree)syntaxTree).File;

            var include = includeFileResolver.OpenInclude(includeDirective.TrimmedFilename, currentFile);

            if (include == null)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var fileSpan = new CodeAnalysis.Text.SourceFileSpan(include, new CodeAnalysis.Text.TextSpan(0, 0));

            var definitionItem = DefinitionItem.Create(
                ImmutableArray <string> .Empty,
                ImmutableArray <TaggedText> .Empty,
                new DocumentSpan(document, fileSpan),
                ImmutableArray <TaggedText> .Empty);

            return(ImmutableArray.Create(definitionItem));
        }
Ejemplo n.º 2
0
        private async TPL.Task <ImmutableArray <DefinitionItem> > GetDefinitionItemsAsync(Document document, int position, CancellationToken cancellationToken)
        {
            var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient;

            if (lspClient == null)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var textDocumentPositionParams = ProtocolConversions.PositionToTextDocumentPositionParams(position, text, document);

            var response = await lspClient.RequestAsync(LSP.Methods.TextDocumentDefinition.ToLSRequest(), textDocumentPositionParams, cancellationToken).ConfigureAwait(false);

            var locations = ((JToken)response)?.ToObject <LSP.Location[]>();

            if (locations == null)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var definitionItems = ImmutableArray.CreateBuilder <DefinitionItem>();

            foreach (var location in locations)
            {
                DocumentSpan?documentSpan;
                if (lspClient.ProtocolConverter.IsExternalDocument(location.Uri))
                {
                    var externalDocument = _remoteWorkspace.GetOrAddExternalDocument(location.Uri.LocalPath, document.Project.Language);
                    var externalText     = await externalDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    var textSpan = ProtocolConversions.RangeToTextSpan(location.Range, externalText);
                    documentSpan = new DocumentSpan(externalDocument, textSpan);
                }
                else
                {
                    documentSpan = await _remoteWorkspace.GetDocumentSpanFromLocation(location, cancellationToken).ConfigureAwait(false);

                    if (documentSpan == null)
                    {
                        continue;
                    }
                }

                definitionItems.Add(DefinitionItem.Create(ImmutableArray <string> .Empty, ImmutableArray <TaggedText> .Empty, documentSpan.Value));
            }

            return(definitionItems.ToImmutable());
        }
            private DefinitionItem GetOrCreateDefinitionItem(VSTypeScriptDefinitionItem item)
            {
                lock (_definitionItemMap)
                {
                    if (!_definitionItemMap.TryGetValue(item, out var result))
                    {
                        result = DefinitionItem.Create(
                            item.Tags,
                            item.DisplayParts,
                            item.SourceSpans,
                            item.NameDisplayParts,
                            item.Properties,
                            item.DisplayableProperties,
                            item.DisplayIfNoReferences);
                        _definitionItemMap.Add(item, result);
                    }

                    return(result);
                }
            }
Ejemplo n.º 4
0
        public async Task FindImplementationsAsync(Document document, int position, IFindUsagesContext context)
        {
            var text = await document.GetTextAsync().ConfigureAwait(false);

            var lspClient = _roslynLspClientServiceFactory.ActiveLanguageServerClient;

            if (lspClient == null)
            {
                return;
            }

            var documentPositionParams = ProtocolConversions.PositionToTextDocumentPositionParams(position, text, document);

            var response = await lspClient.RequestAsync(LiveShareProtocol.Methods.TextDocumentImplementations, documentPositionParams, context.CancellationToken).ConfigureAwait(false);

            var locations = ((JToken)response)?.ToObject <LSP.Location[]>();

            if (locations == null)
            {
                return;
            }

            foreach (var location in locations)
            {
                var documentSpan = await _remoteLanguageServiceWorkspace.GetDocumentSpanFromLocation(location, context.CancellationToken).ConfigureAwait(false);

                if (documentSpan == null)
                {
                    continue;
                }

                // Get the text for the line containing the definition to show in the UI.
                var docText = await documentSpan.Value.Document.GetTextAsync(context.CancellationToken).ConfigureAwait(false);

                var lineText = docText.GetSubText(docText.Lines[location.Range.Start.Line].Span).ToString();

                await context.OnDefinitionFoundAsync(DefinitionItem.Create(ImmutableArray <string> .Empty,
                                                                           ImmutableArray.Create(new TaggedText(TextTags.Text, lineText)), documentSpan.Value)).ConfigureAwait(false);
            }
        }
Ejemplo n.º 5
0
        protected override async Task <ImmutableArray <DefinitionItem> > GetSyntacticDefinitionsAsync(Document document, int position, CancellationToken cancellationToken)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var sourceLocation = syntaxTree.MapRootFilePosition(position);
            var syntaxFacts    = document.GetLanguageService <ISyntaxFactsService>();
            var syntaxToken    = (SyntaxToken)await syntaxTree.GetTouchingTokenAsync(sourceLocation, x => true, cancellationToken, findInsideTrivia : true).ConfigureAwait(false);

            var empty = ImmutableArray <DefinitionItem> .Empty;

            if (syntaxToken == null)
            {
                return(empty);
            }

            if (syntaxToken.MacroReference == null)
            {
                return(empty);
            }

            var nameToken = syntaxToken.MacroReference.NameToken;

            if (!nameToken.SourceRange.ContainsOrTouches(sourceLocation))
            {
                return(empty);
            }

            if (!nameToken.FileSpan.IsInRootFile)
            {
                return(empty);
            }

            var definitionItem = DefinitionItem.Create(
                ImmutableArray <string> .Empty,
                ImmutableArray <TaggedText> .Empty,
                new DocumentSpan(document, syntaxToken.MacroReference.DefineDirective.MacroName.FileSpan),
                ImmutableArray <TaggedText> .Empty);

            return(ImmutableArray.Create(definitionItem));
        }
        private static ImmutableArray <DefinitionItem> GetMacroDefinitionItem(LogicalDocument document, CodeAnalysis.Text.SourceLocation sourceLocation, SyntaxToken syntaxToken)
        {
            var nameToken = syntaxToken.MacroReference.NameToken;

            if (!nameToken.SourceRange.ContainsOrTouches(sourceLocation))
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            if (!nameToken.FileSpan.IsInRootFile)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var definitionItem = DefinitionItem.Create(
                ImmutableArray <string> .Empty,
                ImmutableArray <TaggedText> .Empty,
                new DocumentSpan(document, syntaxToken.MacroReference.DefineDirective.MacroName.FileSpan),
                ImmutableArray <TaggedText> .Empty);

            return(ImmutableArray.Create(definitionItem));
        }
        private static async Task <DefinitionItem> ToDefinitionItemAsync(
            this ISymbol definition,
            Project project,
            bool includeHiddenLocations,
            bool includeClassifiedSpans,
            CancellationToken cancellationToken)
        {
            // Ensure we're working with the original definition for the symbol. I.e. When we're
            // creating definition items, we want to create them for types like Dictionary<TKey,TValue>
            // not some random instantiation of that type.
            //
            // This ensures that the type will both display properly to the user, as well as ensuring
            // that we can accurately resolve the type later on when we try to navigate to it.
            definition = definition.OriginalDefinition;

            var displayParts     = definition.ToDisplayParts(GetFormat(definition)).ToTaggedText();
            var nameDisplayParts = definition.ToDisplayParts(s_namePartsFormat).ToTaggedText();

            var tags = GlyphTags.GetTags(definition.GetGlyph());
            var displayIfNoReferences = definition.ShouldShowWithNoReferenceLocations(
                showMetadataSymbolsWithoutReferences: false);

            var sourceLocations = ArrayBuilder <DocumentSpan> .GetInstance();

            var properties = GetProperties(definition);

            // If it's a namespace, don't create any normal location.  Namespaces
            // come from many different sources, but we'll only show a single
            // root definition node for it.  That node won't be navigable.
            if (definition.Kind != SymbolKind.Namespace)
            {
                foreach (var location in definition.Locations)
                {
                    if (location.IsInMetadata)
                    {
                        return(DefinitionItem.CreateMetadataDefinition(
                                   tags, displayParts, nameDisplayParts, project,
                                   definition, properties, displayIfNoReferences));
                    }
                    else if (location.IsInSource)
                    {
                        if (!location.IsVisibleSourceLocation() &&
                            !includeHiddenLocations)
                        {
                            continue;
                        }

                        var document = project.Solution.GetDocument(location.SourceTree);
                        if (document != null)
                        {
                            var documentLocation = !includeClassifiedSpans
                  ? new DocumentSpan(document, location.SourceSpan)
                  : await ClassifiedSpansAndHighlightSpanFactory.GetClassifiedDocumentSpanAsync(
                                document, location.SourceSpan, cancellationToken).ConfigureAwait(false);

                            sourceLocations.Add(documentLocation);
                        }
                    }
                }
            }

            if (sourceLocations.Count == 0)
            {
                // If we got no definition locations, then create a sentinel one
                // that we can display but which will not allow navigation.
                return(DefinitionItem.CreateNonNavigableItem(
                           tags, displayParts,
                           DefinitionItem.GetOriginationParts(definition),
                           properties, displayIfNoReferences));
            }

            return(DefinitionItem.Create(
                       tags, displayParts, sourceLocations.ToImmutableAndFree(),
                       nameDisplayParts, properties, displayIfNoReferences));
        }
        private static async Task <DefinitionItem> ToDefinitionItemAsync(
            this ISymbol definition,
            Solution solution,
            bool isPrimary,
            bool includeHiddenLocations,
            bool includeClassifiedSpans,
            FindReferencesSearchOptions options,
            CancellationToken cancellationToken)
        {
            // Ensure we're working with the original definition for the symbol. I.e. When we're
            // creating definition items, we want to create them for types like Dictionary<TKey,TValue>
            // not some random instantiation of that type.
            //
            // This ensures that the type will both display properly to the user, as well as ensuring
            // that we can accurately resolve the type later on when we try to navigate to it.
            if (!definition.IsTupleField())
            {
                // In an earlier implementation of the compiler APIs, tuples and tuple fields symbols were definitions
                // We pretend this is still the case
                definition = definition.OriginalDefinition;
            }

            var displayParts     = GetDisplayParts(definition);
            var nameDisplayParts = definition.ToDisplayParts(s_namePartsFormat).ToTaggedText();

            var tags = GlyphTags.GetTags(definition.GetGlyph());
            var displayIfNoReferences = definition.ShouldShowWithNoReferenceLocations(
                options, showMetadataSymbolsWithoutReferences: false);

            using var sourceLocationsDisposer = ArrayBuilder <DocumentSpan> .GetInstance(out var sourceLocations);

            var properties = GetProperties(definition, isPrimary);

            // If it's a namespace, don't create any normal location.  Namespaces
            // come from many different sources, but we'll only show a single
            // root definition node for it.  That node won't be navigable.
            if (definition.Kind != SymbolKind.Namespace)
            {
                foreach (var location in definition.Locations)
                {
                    if (location.IsInMetadata)
                    {
                        return(DefinitionItem.CreateMetadataDefinition(
                                   tags, displayParts, nameDisplayParts, solution,
                                   definition, properties, displayIfNoReferences));
                    }
                    else if (location.IsInSource)
                    {
                        if (!location.IsVisibleSourceLocation() &&
                            !includeHiddenLocations)
                        {
                            continue;
                        }

                        var document = solution.GetDocument(location.SourceTree);
                        if (document != null)
                        {
                            var documentLocation = !includeClassifiedSpans
                                ? new DocumentSpan(document, location.SourceSpan)
                                : await ClassifiedSpansAndHighlightSpanFactory.GetClassifiedDocumentSpanAsync(
                                document, location.SourceSpan, cancellationToken).ConfigureAwait(false);

                            sourceLocations.Add(documentLocation);
                        }
                        else
                        {
                            // Was this a source generated tree? If so, we don't have a document representaion (yet) so
                            // we'll create a metadata symbol which will later be handled by the symbol navigation service
                            // that way. Once we represent generated source trees as propery documents, we'll update the code above
                            // to correctly make this item.
                            var project            = solution.GetOriginatingProject(definition);
                            var generatorRunResult = await project.GetGeneratorDriverRunResultAsync(cancellationToken).ConfigureAwait(false);

                            if (generatorRunResult.TryGetGeneratorAndHint(location.SourceTree, out _, out _))
                            {
                                return(DefinitionItem.CreateMetadataDefinition(
                                           tags, displayParts, nameDisplayParts, solution,
                                           definition, properties, displayIfNoReferences));
                            }
                        }
                    }
                }
            }

            if (sourceLocations.Count == 0)
            {
                // If we got no definition locations, then create a sentinel one
                // that we can display but which will not allow navigation.
                return(DefinitionItem.CreateNonNavigableItem(
                           tags, displayParts,
                           DefinitionItem.GetOriginationParts(definition),
                           properties, displayIfNoReferences));
            }

            var displayableProperties = AbstractReferenceFinder.GetAdditionalFindUsagesProperties(definition);

            return(DefinitionItem.Create(
                       tags, displayParts, sourceLocations.ToImmutable(),
                       nameDisplayParts, properties, displayableProperties, displayIfNoReferences));
        }