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 implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Dima committed Nov 20, 2018
1 parent f26c88f commit 4100090
Show file tree
Hide file tree
Showing 2 changed files with 95 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 @@ -46,6 +46,7 @@ import { buildCode } from './goBuild';
import { installCurrentPackage } from './goInstall';
import { updateWorkspaceModCache } from './goModules';
import { setGlobalState } from './stateUtils';
import { GoTypeDefinitionProvider } from './goTypeDefinition';

export let buildDiagnosticCollection: vscode.DiagnosticCollection;
export let lintDiagnosticCollection: vscode.DiagnosticCollection;
Expand Down Expand Up @@ -158,6 +159,7 @@ export function activate(ctx: vscode.ExtensionContext): void {
registerCompletionProvider(ctx);
ctx.subscriptions.push(vscode.languages.registerHoverProvider(GO_MODE, new GoHoverProvider()));
ctx.subscriptions.push(vscode.languages.registerDefinitionProvider(GO_MODE, new GoDefinitionProvider()));
ctx.subscriptions.push(vscode.languages.registerTypeDefinitionProvider(GO_MODE, new GoTypeDefinitionProvider()));
ctx.subscriptions.push(vscode.languages.registerReferenceProvider(GO_MODE, new GoReferenceProvider()));
ctx.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(GO_MODE, new GoDocumentSymbolProvider()));
ctx.subscriptions.push(vscode.languages.registerWorkspaceSymbolProvider(new GoWorkspaceSymbolProvider()));
Expand Down
93 changes: 93 additions & 0 deletions src/goTypeDefinition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*---------------------------------------------------------
* 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 } 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 references.');
}

let filename = canonicalizeGOPATHPrefix(document.fileName);
let cwd = path.dirname(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) {
return resolve(null);
}

guruOutput.value.typespos.forEach(ref => {
let match = /^(.*):(\d+):(\d+)/.exec(ref.objpos);
if (!match) return;
let [_, file, lineStartStr, colStartStr] = match;
let referenceResource = vscode.Uri.file(path.resolve(cwd, file));
let range = new vscode.Range(
+lineStartStr - 1, +colStartStr - 1, +lineStartStr - 1, +colStartStr
);
results.push(new vscode.Location(referenceResource, range));
});

resolve(results);
} catch (e) {
reject(e);
}
});
if (process.pid) {
process.stdin.end(getFileArchive(document));
}
token.onCancellationRequested(() =>
killTree(process.pid)
);
});
}
}

0 comments on commit 4100090

Please sign in to comment.