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)); }
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); } }
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); } }
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)); }