Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Commit

Permalink
Go to Type Definition command implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Dima committed Nov 21, 2018
1 parent f26c88f commit 7dabda9
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/goMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { GoHoverProvider } from './goExtraInfo';
import { GoDefinitionProvider } from './goDeclaration';
import { GoReferenceProvider } from './goReferences';
import { GoImplementationProvider } from './goImplementations';
import { GoTypeDefinitionProvider } from './goTypeDefinition';
import { GoDocumentFormattingEditProvider } from './goFormat';
import { GoRenameProvider } from './goRename';
import { GoDocumentSymbolProvider } from './goOutline';
Expand Down Expand Up @@ -180,6 +181,7 @@ export function activate(ctx: vscode.ExtensionContext): void {
ctx.subscriptions.push(vscode.languages.registerCodeActionsProvider(GO_MODE, new GoCodeActionProvider()));
ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, testCodeLensProvider));
ctx.subscriptions.push(vscode.languages.registerCodeLensProvider(GO_MODE, referencesCodeLensProvider));
ctx.subscriptions.push(vscode.languages.registerTypeDefinitionProvider(GO_MODE, new GoTypeDefinitionProvider()));
ctx.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('go', new GoDebugConfigurationProvider()));

buildDiagnosticCollection = vscode.languages.createDiagnosticCollection('go');
Expand Down
95 changes: 95 additions & 0 deletions src/goTypeDefinition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------*/

'use strict';

import vscode = require('vscode');
import cp = require('child_process');
import path = require('path');
import { byteOffsetAt, getBinPath, canonicalizeGOPATHPrefix, getFileArchive, killTree } from './util';
import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';
import { getToolsEnvVars } from './util';

interface GuruDescribeOutput {
desc: string;
pos: string;
detail: string;
value: GuruDescribeValueOutput;
}

interface GuruDescribeValueOutput {
type: string;
value: string;
objpos: string;
typespos: GuruDefinitionOutput[];
}

interface GuruDefinitionOutput {
objpos: string;
desc: string;
}

export class GoTypeDefinitionProvider implements vscode.TypeDefinitionProvider {
provideTypeDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<vscode.Definition> {
return new Promise<vscode.Location[]>((resolve, reject) => {
let goGuru = getBinPath('guru');
if (!path.isAbsolute(goGuru)) {
promptForMissingTool('guru');
return reject('Cannot find tool "guru" to find type definitions.');
}

let filename = canonicalizeGOPATHPrefix(document.fileName);
let offset = byteOffsetAt(document, position);
let env = getToolsEnvVars();
let buildTags = vscode.workspace.getConfiguration('go', document.uri)['buildTags'];
let args = buildTags ? ['-tags', buildTags] : [];
args.push('-json', '-modified', 'describe', `${filename}:#${offset.toString()}`);

let process = cp.execFile(goGuru, args, { env }, (err, stdout, stderr) => {
try {
if (err && (<any>err).code === 'ENOENT') {
promptForMissingTool('guru');
return resolve(null);
}

if (err) {
return reject(err);
}

let guruOutput = <GuruDescribeOutput>JSON.parse(stdout.toString());
let results: vscode.Location[] = [];

if (!guruOutput.value || !guruOutput.value.typespos) {
if (guruOutput.value && guruOutput.value.type) {
promptForUpdatingTool('guru');
}
return resolve(null);
}

guruOutput.value.typespos.forEach(ref => {
let match = /^(.*):(\d+):(\d+)/.exec(ref.objpos);
if (!match) {
return;
}
let [_, file, line, col] = match;
let referenceResource = vscode.Uri.file(file);
let pos = new vscode.Position(parseInt(line) - 1, parseInt(col) - 1);
results.push(new vscode.Location(referenceResource, pos));
});

resolve(results);
} catch (e) {
reject(e);
}
});
if (process.pid) {
process.stdin.end(getFileArchive(document));
}
token.onCancellationRequested(() =>
killTree(process.pid)
);
});
}
}
1 change: 1 addition & 0 deletions test/go.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ suite('Go Extension Tests', () => {
return vscode.workspace.openTextDocument(uri).then((textDocument) => {
let promises = testCases.map(([position, expected, expectedDoc, expectedParams]) =>
provider.provideSignatureHelp(textDocument, position, null).then(sigHelp => {
assert.ok(sigHelp, `No signature for gogetdocTestData/test.go:${position}`);
assert.equal(sigHelp.signatures.length, 1, 'unexpected number of overloads');
assert.equal(sigHelp.signatures[0].label, expected);
assert.equal(sigHelp.signatures[0].documentation, expectedDoc);
Expand Down

0 comments on commit 7dabda9

Please sign in to comment.