private static CompletionItem CreateCompletionItem(XamlCompletionItem xamlCompletion, DocumentId documentId, SourceText text, Position position) { var item = new VSCompletionItem { Label = xamlCompletion.DisplayText, CommitCharacters = xamlCompletion.CommitCharacters, Detail = xamlCompletion.Detail, InsertText = xamlCompletion.InsertText, Preselect = xamlCompletion.Preselect.GetValueOrDefault(), SortText = xamlCompletion.SortText, FilterText = xamlCompletion.FilterText, Kind = GetItemKind(xamlCompletion.Kind), Description = xamlCompletion.Description, Icon = xamlCompletion.Icon, Data = new CompletionResolveData { ProjectGuid = documentId.ProjectId.Id, DocumentGuid = documentId.Id, Position = position, DisplayText = xamlCompletion.DisplayText } }; if (xamlCompletion.Span.HasValue) { item.TextEdit = new TextEdit { NewText = xamlCompletion.InsertText, Range = ProtocolConversions.LinePositionToRange(text.Lines.GetLinePositionSpan(xamlCompletion.Span.Value)) }; } return(item); }
public async Task <object> HandleAsync(LSP.TextDocumentPositionParams request, RequestContext <Solution> requestContext, CancellationToken cancellationToken) { var document = _solutionProvider.GetDocument(request.TextDocument); if (document == null) { return(Array.Empty <LSP.Location>()); } var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); var locations = await GetDefinitionsWithFindUsagesServiceAsync(document, position, cancellationToken).ConfigureAwait(false); // No definition found - see if we can get metadata as source but that's only applicable for C#\VB. if ((locations.Length == 0) && document.SupportsSemanticModel && this._metadataAsSourceService != null) { var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false); if (symbol?.Locations.FirstOrDefault().IsInMetadata == true) { var declarationFile = await this._metadataAsSourceService.GetGeneratedFileAsync(document.Project, symbol, false, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; return(new LSP.Location[] { new LSP.Location { Uri = new Uri(declarationFile.FilePath), Range = ProtocolConversions.LinePositionToRange(linePosSpan) } }); } } return(locations.ToArray()); }
protected async Task <LSP.Location[]> GetDefinitionAsync(Solution solution, LSP.TextDocumentPositionParams request, bool typeOnly, CancellationToken cancellationToken) { var locations = ArrayBuilder <LSP.Location> .GetInstance(); var document = solution.GetDocumentFromURI(request.TextDocument.Uri); if (document == null) { return(locations.ToArrayAndFree()); } var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); var definitionService = document.Project.LanguageServices.GetService <IGoToDefinitionService>(); var definitions = await definitionService.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false); if (definitions != null && definitions.Count() > 0) { foreach (var definition in definitions) { if (!ShouldInclude(definition, typeOnly)) { continue; } var definitionText = await definition.Document.GetTextAsync(cancellationToken).ConfigureAwait(false); locations.Add(new LSP.Location { Uri = definition.Document.GetURI(), Range = ProtocolConversions.TextSpanToRange(definition.SourceSpan, definitionText), }); } } else if (document.SupportsSemanticModel && _metadataAsSourceFileService != null) { // No definition found - see if we can get metadata as source but that's only applicable for C#\VB. var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false); if (symbol != null && symbol.Locations != null && !symbol.Locations.IsEmpty && symbol.Locations.First().IsInMetadata) { if (!typeOnly || symbol is ITypeSymbol) { var declarationFile = await _metadataAsSourceFileService.GetGeneratedFileAsync(document.Project, symbol, false, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; locations.Add(new LSP.Location { Uri = new Uri(declarationFile.FilePath), Range = ProtocolConversions.LinePositionToRange(linePosSpan), }); } } } return(locations.ToArrayAndFree());
protected async Task <LSP.Location[]?> GetDefinitionAsync(LSP.TextDocumentPositionParams request, bool typeOnly, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) { return(null); } var locations = ArrayBuilder <LSP.Location> .GetInstance(); var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); var findDefinitionService = document.GetRequiredLanguageService <IFindDefinitionService>(); var definitions = await findDefinitionService.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false); if (definitions.Any()) { foreach (var definition in definitions) { if (!ShouldInclude(definition, typeOnly)) { continue; } var location = await ProtocolConversions.TextSpanToLocationAsync( definition.Document, definition.SourceSpan, definition.IsStale, cancellationToken).ConfigureAwait(false); locations.AddIfNotNull(location); } } else if (document.SupportsSemanticModel && _metadataAsSourceFileService != null) { // No definition found - see if we can get metadata as source but that's only applicable for C#\VB. var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false); if (symbol != null && _metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol)) { if (!typeOnly || symbol is ITypeSymbol) { var options = _globalOptions.GetMetadataAsSourceOptions(document.Project.LanguageServices); var declarationFile = await _metadataAsSourceFileService.GetGeneratedFileAsync(document.Project, symbol, signaturesOnly : false, options, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; locations.Add(new LSP.Location { Uri = new Uri(declarationFile.FilePath), Range = ProtocolConversions.LinePositionToRange(linePosSpan), }); } } } return(locations.ToArrayAndFree());
private static CompletionItem CreateCompletionItem( XamlCompletionItem xamlCompletion, DocumentId documentId, SourceText text, Position position, TextDocumentIdentifier textDocument ) { var item = new VSCompletionItem { Label = xamlCompletion.DisplayText, CommitCharacters = xamlCompletion.CommitCharacters, Detail = xamlCompletion.Detail, InsertText = xamlCompletion.InsertText, Preselect = xamlCompletion.Preselect.GetValueOrDefault(), SortText = xamlCompletion.SortText, FilterText = xamlCompletion.FilterText, Kind = GetItemKind(xamlCompletion.Kind), Description = xamlCompletion.Description, Icon = xamlCompletion.Icon, Data = new CompletionResolveData { ProjectGuid = documentId.ProjectId.Id, DocumentGuid = documentId.Id, Position = position, DisplayText = xamlCompletion.DisplayText } }; if (xamlCompletion.Span.HasValue) { item.TextEdit = new TextEdit { NewText = xamlCompletion.InsertText, Range = ProtocolConversions.LinePositionToRange( text.Lines.GetLinePositionSpan(xamlCompletion.Span.Value) ) }; } if (xamlCompletion.EventDescription.HasValue) { item.Command = new Command() { CommandIdentifier = StringConstants.CreateEventHandlerCommand, Arguments = new object[] { textDocument, xamlCompletion.EventDescription }, Title = CreateEventHandlerCommandTitle }; } return(item); }
// Local functions static async Task <LSP.Location?> ComputeLocationAsync( Document document, int position, DocumentSpan documentSpan, IMetadataAsSourceFileService metadataAsSourceFileService, CancellationToken cancellationToken) { if (documentSpan != default) { // We do have a document span, so compute location normally. return(await ProtocolConversions.DocumentSpanToLocationAsync(documentSpan, cancellationToken).ConfigureAwait(false)); } // If we have no document span, our location may be in metadata or may be a namespace. var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false); if (symbol == null || symbol.Locations.IsEmpty || symbol.Kind == SymbolKind.Namespace) { // Either: // (1) We couldn't find the location in metadata and it's not in any of our known documents. // (2) The symbol is a namespace (and therefore has no location). return(null); } var declarationFile = await metadataAsSourceFileService.GetGeneratedFileAsync( document.Project, symbol, allowDecompilation : false, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; if (string.IsNullOrEmpty(declarationFile.FilePath)) { return(null); } try { return(new LSP.Location { Uri = ProtocolConversions.GetUriFromFilePath(declarationFile.FilePath), Range = ProtocolConversions.LinePositionToRange(linePosSpan), }); } catch (UriFormatException e) when(FatalError.ReportAndCatch(e)) { // We might reach this point if the file path is formatted incorrectly. return(null); } }
private static CompletionItem CreateCompletionItem(XamlCompletionItem xamlCompletion, DocumentId documentId, SourceText text, Position position, TextDocumentIdentifier textDocument, Dictionary <XamlCompletionKind, ImmutableArray <VSInternalCommitCharacter> > commitCharactersCach) { var item = new VSInternalCompletionItem { Label = xamlCompletion.DisplayText, VsCommitCharacters = GetCommitCharacters(xamlCompletion, commitCharactersCach), Detail = xamlCompletion.Detail, InsertText = xamlCompletion.InsertText, Preselect = xamlCompletion.Preselect.GetValueOrDefault(), SortText = xamlCompletion.SortText, FilterText = xamlCompletion.FilterText, Kind = GetItemKind(xamlCompletion.Kind), Description = xamlCompletion.Description, Icon = xamlCompletion.Icon, InsertTextFormat = xamlCompletion.IsSnippet ? InsertTextFormat.Snippet : InsertTextFormat.Plaintext, Data = new CompletionResolveData { ProjectGuid = documentId.ProjectId.Id, DocumentGuid = documentId.Id, Position = position, DisplayText = xamlCompletion.DisplayText } }; if (xamlCompletion.Span.HasValue) { item.TextEdit = new TextEdit { NewText = xamlCompletion.InsertText, Range = ProtocolConversions.LinePositionToRange(text.Lines.GetLinePositionSpan(xamlCompletion.Span.Value)) }; } if (xamlCompletion.EventDescription.HasValue) { item.Command = new Command() { CommandIdentifier = StringConstants.CreateEventHandlerCommand, Arguments = new object[] { textDocument, xamlCompletion.EventDescription }, Title = CreateEventHandlerCommandTitle }; } else if (xamlCompletion.RetriggerCompletion) { // Retriger completion after commit item.Command = s_retriggerCompletionCommand; } return(item); }
private static async Task <LSP.Location[]> GetSymbolDefinitionLocationsAsync(XamlSymbolDefinition symbolDefinition, RequestContext context, IMetadataAsSourceFileService metadataAsSourceFileService, CancellationToken cancellationToken) { Contract.ThrowIfNull(symbolDefinition.Symbol); using var _ = ArrayBuilder <LSP.Location> .GetInstance(out var locations); var symbol = symbolDefinition.Symbol; var items = NavigableItemFactory.GetItemsFromPreferredSourceLocations(context.Solution, symbol, displayTaggedParts: null, cancellationToken); if (items.Any()) { foreach (var item in items) { var location = await ProtocolConversions.TextSpanToLocationAsync( item.Document, item.SourceSpan, item.IsStale, cancellationToken).ConfigureAwait(false); locations.AddIfNotNull(location); } } else { var metadataLocation = symbol.Locations.Where(loc => loc.IsInMetadata).FirstOrDefault(); if (metadataLocation != null && metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol)) { var project = context.Document?.GetCodeProject(); if (project != null) { var declarationFile = await metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, allowDecompilation : false, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; locations.Add(new LSP.Location { Uri = new Uri(declarationFile.FilePath), Range = ProtocolConversions.LinePositionToRange(linePosSpan), }); } } } return(locations.ToArray()); }
public async Task <object> HandleAsync(LSP.TextDocumentPositionParams request, RequestContext <Solution> requestContext, CancellationToken cancellationToken) { // LiveShare doesn't go through Roslyn LSP infrastructure, but creating one of our request contexts here is a convenient way to handle // text document lookup var lspContext = LSPHandler.RequestContext.Create(requiresLSPSolution: true, request.TextDocument, null, requestContext.GetClientCapabilities(), _workspaceRegistrationService, null, null, out _); var document = lspContext.Document; if (document == null) { return(Array.Empty <LSP.Location>()); } var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); var locations = await GetDefinitionsWithFindUsagesServiceAsync(document, position, cancellationToken).ConfigureAwait(false); // No definition found - see if we can get metadata as source but that's only applicable for C#\VB. if ((locations.Length == 0) && document.SupportsSemanticModel && this._metadataAsSourceService != null) { var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false); if (symbol?.Locations.FirstOrDefault()?.IsInMetadata == true) { var declarationFile = await this._metadataAsSourceService.GetGeneratedFileAsync(document.Project, symbol, false, cancellationToken).ConfigureAwait(false); var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span; return(new LSP.Location[] { new LSP.Location { Uri = new Uri(declarationFile.FilePath), Range = ProtocolConversions.LinePositionToRange(linePosSpan) } }); } } return(locations.ToArray()); }