public provideTypeDefinition()

in src/goTypeDefinition.ts [39:130]


	public provideTypeDefinition(
		document: vscode.TextDocument,
		position: vscode.Position,
		token: vscode.CancellationToken
	): vscode.ProviderResult<vscode.Definition> {
		const adjustedPos = adjustWordPosition(document, position);
		if (!adjustedPos[0]) {
			return Promise.resolve(null);
		}
		position = adjustedPos[2];

		return new Promise<vscode.Definition>((resolve, reject) => {
			const goGuru = getBinPath('guru');
			if (!path.isAbsolute(goGuru)) {
				promptForMissingTool('guru');
				return reject('Cannot find tool "guru" to find type definitions.');
			}

			const filename = canonicalizeGOPATHPrefix(document.fileName);
			const offset = byteOffsetAt(document, position);
			const env = toolExecutionEnvironment();
			const buildTags = getGoConfig(document.uri)['buildTags'];
			const args = buildTags ? ['-tags', buildTags] : [];
			args.push('-json', '-modified', 'describe', `${filename}:#${offset.toString()}`);

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

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

					const guruOutput = <GuruDescribeOutput>JSON.parse(stdout.toString());
					if (!guruOutput.value || !guruOutput.value.typespos) {
						if (
							guruOutput.value &&
							guruOutput.value.type &&
							!goBuiltinTypes.has(guruOutput.value.type) &&
							guruOutput.value.type !== 'invalid type'
						) {
							console.log("no typespos from guru's output - try to update guru tool");
						}

						// Fall back to position of declaration
						return definitionLocation(document, position, null, false, token).then(
							(definitionInfo) => {
								if (definitionInfo === null || definitionInfo.file === null) {
									return null;
								}
								const definitionResource = vscode.Uri.file(definitionInfo.file);
								const pos = new vscode.Position(definitionInfo.line, definitionInfo.column);
								resolve(new vscode.Location(definitionResource, pos));
							},
							(err) => {
								const miss = parseMissingError(err);
								if (miss[0]) {
									promptForMissingTool(miss[1]);
								} else if (err) {
									return Promise.reject(err);
								}
								return Promise.resolve(null);
							}
						);
					}

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

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