public override async Task <QuickInfoItem?> GetQuickInfoAsync(QuickInfoContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document .GetRequiredSyntaxTreeAsync(cancellationToken) .ConfigureAwait(false); var token = await tree.GetTouchingTokenAsync( position, cancellationToken, findInsideTrivia : true ) .ConfigureAwait(false); var info = await GetQuickInfoAsync(document, token, position, cancellationToken) .ConfigureAwait(false); if (info == null && ShouldCheckPreviousToken(token)) { var previousToken = token.GetPreviousToken(); info = await GetQuickInfoAsync(document, previousToken, position, cancellationToken) .ConfigureAwait(false); } return(info); }
public override async Task <QuickInfoItem?> GetQuickInfoAsync(Document document, int position, CancellationToken cancellationToken) { var extensionManager = _workspace.Services.GetRequiredService <IExtensionManager>(); // returns the first non-empty quick info found (based on provider order) foreach (var provider in GetProviders()) { try { if (!extensionManager.IsDisabled(provider)) { var context = new QuickInfoContext(document, position, cancellationToken); var info = await provider.GetQuickInfoAsync(context).ConfigureAwait(false); if (info != null) { return(info); } } } catch (OperationCanceledException) { throw; } catch (Exception e) when(extensionManager.CanHandleException(provider, e)) { extensionManager.HandleException(provider, e); } } return(null); }
private async Task <(TokenInformation, SupportedPlatformData supportedPlatforms)> ComputeFromLinkedDocumentsAsync( QuickInfoContext context, SyntaxToken token, ImmutableArray <DocumentId> linkedDocumentIds) { // Linked files/shared projects: imagine the following when GOO is false // #if GOO // int x = 3; // #endif // var y = x$$; // // 'x' will bind as an error type, so we'll show incorrect information. // Instead, we need to find the head in which we get the best binding, // which in this case is the one with no errors. var cancellationToken = context.CancellationToken; var document = context.Document; var solution = document.Project.Solution; var workspace = solution.Workspace; var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var mainTokenInformation = BindToken(workspace, semanticModel, token, cancellationToken); var candidateProjects = new List <ProjectId> { document.Project.Id }; var invalidProjects = new List <ProjectId>(); var candidateResults = new List <(DocumentId docId, TokenInformation tokenInformation)> { (document.Id, mainTokenInformation) }; foreach (var linkedDocumentId in linkedDocumentIds) { var linkedDocument = solution.GetRequiredDocument(linkedDocumentId); var linkedModel = await linkedDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var linkedToken = FindTokenInLinkedDocument(token, linkedModel, cancellationToken); if (linkedToken != default) { // Not in an inactive region, so this file is a candidate. candidateProjects.Add(linkedDocumentId.ProjectId); var linkedSymbols = BindToken(workspace, linkedModel, linkedToken, cancellationToken); candidateResults.Add((linkedDocumentId, linkedSymbols)); } } // Take the first result with no errors. // If every file binds with errors, take the first candidate, which is from the current file. var bestBinding = candidateResults.FirstOrNull(c => HasNoErrors(c.tokenInformation.Symbols)) ?? candidateResults.First(); if (bestBinding.tokenInformation.Symbols.IsDefaultOrEmpty) { return(default);
private async Task <QuickInfoItem?> GetQuickInfoAsync( QuickInfoContext context, SyntaxToken token) { if (token != default && token.Span.IntersectsWith(context.Position)) { return(await BuildQuickInfoAsync(context, token).ConfigureAwait(false)); } return(null); }
protected override async Task <QuickInfoItem?> BuildQuickInfoAsync( QuickInfoContext context, SyntaxToken token) { var(tokenInformation, supportedPlatforms) = await ComputeQuickInfoDataAsync(context, token).ConfigureAwait(false); if (tokenInformation.Symbols.IsDefaultOrEmpty) { return(null); } var cancellationToken = context.CancellationToken; var semanticModel = await context.Document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); return(await CreateContentAsync( context.Document.Project.Solution.Workspace, semanticModel, token, tokenInformation, supportedPlatforms, cancellationToken).ConfigureAwait(false)); }
public override async Task <QuickInfoItem?> GetQuickInfoAsync(QuickInfoContext context) { var cancellationToken = context.CancellationToken; var tree = await context.Document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var tokens = await GetTokensAsync(tree, context.Position, context.CancellationToken).ConfigureAwait(false); foreach (var token in tokens) { var info = await GetQuickInfoAsync(context, token).ConfigureAwait(false); if (info != null) { return(info); } } return(null); }
private async Task <(TokenInformation tokenInformation, SupportedPlatformData?supportedPlatforms)> ComputeQuickInfoDataAsync( QuickInfoContext context, SyntaxToken token) { var cancellationToken = context.CancellationToken; var document = context.Document; var linkedDocumentIds = document.GetLinkedDocumentIds(); if (linkedDocumentIds.Any()) { return(await ComputeFromLinkedDocumentsAsync(context, token, linkedDocumentIds).ConfigureAwait(false)); } var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var tokenInformation = BindToken( document.Project.Solution.Workspace, semanticModel, token, cancellationToken); return(tokenInformation, supportedPlatforms : null); }
public abstract Task <QuickInfoItem?> GetQuickInfoAsync(QuickInfoContext context);
protected abstract Task <QuickInfoItem?> BuildQuickInfoAsync(QuickInfoContext context, SyntaxToken token);