Skip to content

Commit

Permalink
Provide source generated file info for workspace symbols (#5338)
Browse files Browse the repository at this point in the history
VSCode side of OmniSharp/omnisharp-roslyn#2431. I also updated the source generated doc provider to have a lazy-fetch option, as we don't want to fetch and cache generated files for every single symbol that gets returned in a workspace symbol request.
  • Loading branch information
333fred authored Aug 13, 2022
1 parent 1fb99b8 commit c797f86
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 11 deletions.
36 changes: 33 additions & 3 deletions src/features/sourceGeneratedDocumentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import * as serverUtils from '../omnisharp/utils';
import { Event, EventEmitter, TextDocument, TextDocumentContentProvider, TextEditor, Uri, window, workspace } from 'vscode';
import { CancellationToken, Event, EventEmitter, TextDocument, TextDocumentContentProvider, TextEditor, Uri, window, workspace } from 'vscode';
import { IDisposable } from '../Disposable';
import { SourceGeneratedFileInfo, SourceGeneratedFileResponse, UpdateType } from '../omnisharp/protocol';
import { OmniSharpServer } from '../omnisharp/server';
Expand Down Expand Up @@ -89,6 +89,27 @@ export default class SourceGeneratedDocumentProvider implements TextDocumentCont
return undefined;
}

public addSourceGeneratedFileWithoutInitialContent(fileInfo: SourceGeneratedFileInfo, fileName: string): Uri {
if (this._documents.has(fileInfo)) {
// Raced with something, return the existing one
return this.tryGetExistingSourceGeneratedFile(fileInfo);
}

const uri = this.getUriForName(fileName);
const uriString = uri.toString();

if (this._uriToDocumentInfo.has(uriString)) {
this._documents.delete(fileInfo);
this._uriToDocumentInfo.delete(uriString);
}

// Provide will see the null and retrieve the file when asked.
this._documents.set(fileInfo, null);
this._uriToDocumentInfo.set(uriString, fileInfo);

return uri;
}

public addSourceGeneratedFile(fileInfo: SourceGeneratedFileInfo, response: SourceGeneratedFileResponse): Uri {
if (this._documents.has(fileInfo)) {
// Raced with something, return the existing one
Expand Down Expand Up @@ -117,8 +138,17 @@ export default class SourceGeneratedDocumentProvider implements TextDocumentCont
return uri;
}

public provideTextDocumentContent(uri: Uri): string {
return this._documents.get(this._uriToDocumentInfo.get(uri.toString())).Source;
public async provideTextDocumentContent(uri: Uri, token: CancellationToken): Promise<string> {
const fileInfo = this._uriToDocumentInfo.get(uri.toString());
let response = this._documents.get(fileInfo);

if (response === null) {
// No content yet, get it
response = await serverUtils.getSourceGeneratedFile(this.server, fileInfo, token);
this._documents.set(fileInfo, response);
}

return response.Source;
}

private getUriForName(sourceName: string): Uri {
Expand Down
30 changes: 23 additions & 7 deletions src/features/workspaceSymbolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@ import OptionProvider from '../observers/OptionProvider';
import * as protocol from '../omnisharp/protocol';
import * as serverUtils from '../omnisharp/utils';
import { toRange } from '../omnisharp/typeConversion';
import { CancellationToken, Uri, WorkspaceSymbolProvider, SymbolInformation, SymbolKind } from 'vscode';
import { CancellationToken, Uri, WorkspaceSymbolProvider, SymbolInformation, SymbolKind, Location } from 'vscode';
import { LanguageMiddlewareFeature } from '../omnisharp/LanguageMiddlewareFeature';
import SourceGeneratedDocumentProvider from './sourceGeneratedDocumentProvider';


export default class OmnisharpWorkspaceSymbolProvider extends AbstractSupport implements WorkspaceSymbolProvider {

constructor(server: OmniSharpServer, private optionProvider: OptionProvider, languageMiddlewareFeature: LanguageMiddlewareFeature) {
constructor(
server: OmniSharpServer,
private optionProvider: OptionProvider,
languageMiddlewareFeature: LanguageMiddlewareFeature,
private sourceGeneratedDocumentProvider: SourceGeneratedDocumentProvider) {
super(server, languageMiddlewareFeature);
}

Expand All @@ -32,19 +37,30 @@ export default class OmnisharpWorkspaceSymbolProvider extends AbstractSupport im
try {
let res = await serverUtils.findSymbols(this._server, { Filter: search, MaxItemsToReturn: maxItemsToReturn, FileName: '' }, token);
if (res && Array.isArray(res.QuickFixes)) {
return res.QuickFixes.map(OmnisharpWorkspaceSymbolProvider._asSymbolInformation);
return res.QuickFixes.map(symbol => this._asSymbolInformation(symbol));
}
}
catch (error) {
return [];
}
}

private static _asSymbolInformation(symbolInfo: protocol.SymbolLocation): SymbolInformation {
private _asSymbolInformation(symbolInfo: protocol.SymbolLocation): SymbolInformation {
let uri: Uri;
if (symbolInfo.GeneratedFileInfo) {
uri = this.sourceGeneratedDocumentProvider.addSourceGeneratedFileWithoutInitialContent(symbolInfo.GeneratedFileInfo, symbolInfo.FileName);
}
else {
uri = Uri.file(symbolInfo.FileName);
}

const location = new Location(uri, toRange(symbolInfo));

return new SymbolInformation(symbolInfo.Text, OmnisharpWorkspaceSymbolProvider._toKind(symbolInfo),
toRange(symbolInfo),
Uri.file(symbolInfo.FileName));
return new SymbolInformation(
symbolInfo.Text,
OmnisharpWorkspaceSymbolProvider._toKind(symbolInfo),
symbolInfo.ContainingSymbolName ?? "",
location);
}

private static _toKind(symbolInfo: protocol.SymbolLocation): SymbolKind {
Expand Down
2 changes: 1 addition & 1 deletion src/omnisharp/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an
}
localDisposables.add(vscode.languages.registerCompletionItemProvider(documentSelector, completionProvider, '.', ' '));
localDisposables.add(vscode.commands.registerCommand(CompletionAfterInsertCommand, async (item) => completionProvider.afterInsert(item)));
localDisposables.add(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(server, optionProvider, languageMiddlewareFeature)));
localDisposables.add(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(server, optionProvider, languageMiddlewareFeature, sourceGeneratedDocumentProvider)));
localDisposables.add(vscode.languages.registerSignatureHelpProvider(documentSelector, new SignatureHelpProvider(server, languageMiddlewareFeature), '(', ','));
// Since the CodeActionProvider registers its own commands, we must instantiate it and add it to the localDisposables
// so that it will be cleaned up if OmniSharp is restarted.
Expand Down
2 changes: 2 additions & 0 deletions src/omnisharp/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ export interface QuickFix {

export interface SymbolLocation extends QuickFix {
Kind: string;
ContainingSymbolName?: string;
GeneratedFileInfo?: SourceGeneratedFileInfo;
}

export interface QuickFixResponse {
Expand Down

0 comments on commit c797f86

Please sign in to comment.