Skip to content

Commit 44b4b15

Browse files
committed
Implemented support for "Go to definition" to "3rd party" assemblies using type metadata. Fixes #165
1 parent fe328c0 commit 44b4b15

File tree

4 files changed

+77
-9
lines changed

4 files changed

+77
-9
lines changed

src/features/definitionProvider.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,57 @@
66
'use strict';
77

88
import AbstractSupport from './abstractProvider';
9+
import {MetadataRequest, GoToDefinitionRequest} from '../omnisharp/protocol';
910
import * as serverUtils from '../omnisharp/utils';
1011
import {createRequest, toLocation} from '../omnisharp/typeConvertion';
11-
import {TextDocument, Position, Location, CancellationToken, DefinitionProvider} from 'vscode';
12+
import {workspace, window, Uri, TextDocument, Position, Location, CancellationToken, DefinitionProvider, Selection, TextEditorRevealType} from 'vscode';
1213

1314
export default class CSharpDefinitionProvider extends AbstractSupport implements DefinitionProvider {
1415

1516
public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Location> {
1617

17-
let req = createRequest(document, position);
18+
let req = <GoToDefinitionRequest>createRequest(document, position);
19+
req.WantMetadata = true;
1820

1921
return serverUtils.goToDefinition(this._server, req, token).then(value => {
22+
2023
if (value && value.FileName) {
2124
return toLocation(value);
22-
}
25+
} else if (value.MetadataSource) {
26+
27+
let lineNumber = value.Line;
28+
let column = value.Column;
29+
30+
serverUtils.getMetadata(this._server, <MetadataRequest> {
31+
AssemblyName: value.MetadataSource.AssemblyName,
32+
VersionNumber: value.MetadataSource.VersionNumber,
33+
ProjectName: value.MetadataSource.ProjectName,
34+
Language: value.MetadataSource.Language,
35+
TypeName: value.MetadataSource.TypeName
36+
}).then(metadataResponse => {
37+
if (!metadataResponse || !metadataResponse.Source || !metadataResponse.SourceName) {
38+
return;
39+
}
40+
41+
const scheme = "omnisharp-metadata";
42+
let temporaryDocumentContentProviderRegistration = workspace.registerTextDocumentContentProvider(scheme, {
43+
provideTextDocumentContent: function(uri) {
44+
return metadataResponse.Source;
45+
}
46+
});
47+
48+
let uri = Uri.parse(scheme + "://" + metadataResponse.SourceName.replace(/\\/g, "/").replace(/(.*)\/(.*)/g, "$1/[metadata] $2"));
49+
workspace.openTextDocument(uri).then(document => {
50+
temporaryDocumentContentProviderRegistration.dispose();
51+
52+
window.showTextDocument(document, null, false).then(editor => {
53+
let position = new Position(lineNumber - 1, column - 1);
54+
editor.selection = new Selection(position, position);
55+
editor.revealRange(editor.document.lineAt(position.line).range, TextEditorRevealType.InCenter);
56+
});
57+
});
58+
});
59+
}
2360
});
2461
}
2562
}

src/omnisharp/protocol.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export module Requests {
2626
export const SignatureHelp = '/signatureHelp';
2727
export const TypeLookup = '/typelookup';
2828
export const UpdateBuffer = '/updatebuffer';
29+
export const Metadata = '/metadata';
2930
}
3031

3132
export interface Request {
@@ -36,6 +37,11 @@ export interface Request {
3637
Changes?: LinePositionSpanTextChange[];
3738
}
3839

40+
export interface GoToDefinitionRequest extends Request
41+
{
42+
WantMetadata?: boolean;
43+
}
44+
3945
export interface LinePositionSpanTextChange {
4046
NewText: string;
4147
StartLine: number;
@@ -44,6 +50,23 @@ export interface LinePositionSpanTextChange {
4450
EndColumn: number;
4551
}
4652

53+
export interface MetadataSource {
54+
AssemblyName: string;
55+
ProjectName: string;
56+
VersionNumber: string;
57+
Language: string;
58+
TypeName: string;
59+
}
60+
61+
export interface MetadataRequest extends MetadataSource {
62+
Timeout?: number;
63+
}
64+
65+
export interface MetadataResponse {
66+
SourceName: string;
67+
Source: string;
68+
}
69+
4770
export interface UpdateBufferRequest extends Request {
4871
FromDisk?: boolean;
4972
}
@@ -119,6 +142,10 @@ export interface ResourceLocation {
119142
Column: number;
120143
}
121144

145+
export interface GoToDefinitionResponse extends ResourceLocation {
146+
MetadataSource?: MetadataSource;
147+
}
148+
122149
export interface Error {
123150
Message: string;
124151
Line: number;

src/omnisharp/server.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export abstract class OmnisharpServer {
109109
return {
110110
path: config.get<string>('omnisharp'),
111111
usesMono: config.get<boolean>('omnisharpUsesMono')
112-
}
112+
};
113113
}
114114

115115
private _recordRequestDelay(requestName: string, elapsedTime: number) {
@@ -122,7 +122,7 @@ export abstract class OmnisharpServer {
122122
tracker.reportDelay(elapsedTime);
123123
}
124124

125-
private _reportTelemetry() {
125+
private _reportTelemetry() {
126126
const delayTrackers = this._delayTrackers;
127127

128128
for (const path in delayTrackers) {
@@ -235,7 +235,7 @@ export abstract class OmnisharpServer {
235235

236236
private _start(launchTarget: LaunchTarget): Promise<void> {
237237
const options = this._readOptions();
238-
238+
239239
let flavor: omnisharp.Flavor;
240240
if (options.path !== undefined && options.usesMono === true) {
241241
flavor = omnisharp.Flavor.Mono;
@@ -416,7 +416,7 @@ export abstract class OmnisharpServer {
416416

417417
throw err;
418418
}
419-
419+
420420
const config = vscode.workspace.getConfiguration();
421421
const proxy = config.get<string>('http.proxy');
422422
const strictSSL = config.get('http.proxyStrictSSL', true);

src/omnisharp/utils.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ export function getCodeActions(server: OmnisharpServer, request: protocol.V2.Get
4545
return server.makeRequest<protocol.V2.GetCodeActionsResponse>(protocol.V2.Requests.GetCodeActions, request, token);
4646
}
4747

48-
export function goToDefinition(server: OmnisharpServer, request: protocol.Request, token: vscode.CancellationToken) {
49-
return server.makeRequest<protocol.ResourceLocation>(protocol.Requests.GoToDefinition, request);
48+
export function goToDefinition(server: OmnisharpServer, request: protocol.GoToDefinitionRequest, token: vscode.CancellationToken) {
49+
return server.makeRequest<protocol.GoToDefinitionResponse>(protocol.Requests.GoToDefinition, request);
5050
}
5151

5252
export function rename(server: OmnisharpServer, request: protocol.RenameRequest, token: vscode.CancellationToken) {
@@ -73,6 +73,10 @@ export function updateBuffer(server: OmnisharpServer, request: protocol.UpdateBu
7373
return server.makeRequest<boolean>(protocol.Requests.UpdateBuffer, request);
7474
}
7575

76+
export function getMetadata(server: OmnisharpServer, request: protocol.MetadataRequest) {
77+
return server.makeRequest<protocol.MetadataResponse>(protocol.Requests.Metadata, request);
78+
}
79+
7680
export function getTestStartInfo(server: OmnisharpServer, request: protocol.V2.GetTestStartInfoRequest) {
7781
return server.makeRequest<protocol.V2.GetTestStartInfoResponse>(protocol.V2.Requests.GetTestStartInfo, request);
7882
}

0 commit comments

Comments
 (0)