src/goTools.ts: apply timeout (10s) in gocode close call

Also, report the tool version and the installation location
in the install success message, and include `-x` output in the
install failure message.

Update golang/vscode-go#362

Change-Id: Ie84a755fb1008bf048acec9c707b89a14cd960c0
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/243700
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
index ac33415..9a2d81a 100644
--- a/src/goInstallTools.ts
+++ b/src/goInstallTools.ts
@@ -177,7 +177,7 @@
 	envForTools: NodeJS.Dict<string>, modulesOn: boolean): Promise<string> {
 	// Some tools may have to be closed before we reinstall them.
 	if (tool.close) {
-		const reason = await tool.close();
+		const reason = await tool.close(envForTools);
 		if (reason) {
 			return reason;
 		}
@@ -239,7 +239,9 @@
 			const outputFile = path.join(gopath, 'bin', process.platform === 'win32' ? `${tool.name}.exe` : tool.name);
 			await execFile(goVersion.binaryPath, ['build', '-o', outputFile, importPath], opts);
 		}
-		outputChannel.appendLine(`Installing ${importPath} SUCCEEDED`);
+		const toolImportPath = tool.version ? importPath + '@' + tool.version : importPath;
+		const toolInstallPath = getBinPath(tool.name);
+		outputChannel.appendLine(`Installing ${toolImportPath} (${toolInstallPath}) SUCCEEDED`);
 	} catch (e) {
 		outputChannel.appendLine(`Installing ${importPath} FAILED`);
 		result = `failed to install ${tool}: ${e} ${output} `;
diff --git a/src/goTools.ts b/src/goTools.ts
index 91d72dc..0153fe3 100644
--- a/src/goTools.ts
+++ b/src/goTools.ts
@@ -36,7 +36,7 @@
 	// close performs any shutdown tasks that a tool must execute before a new
 	// version is installed. It returns a string containing an error message on
 	// failure.
-	close?: () => Promise<string>;
+	close?: (env: NodeJS.Dict<string>) => Promise<string>;
 }
 
 /**
@@ -182,19 +182,20 @@
 		importPath: 'github.com/mdempsky/gocode',
 		isImportant: true,
 		description: 'Auto-completion, does not work with modules',
-		close: async (): Promise<string> => {
+		close: async (env: NodeJS.Dict<string>): Promise<string> => {
 			const toolBinPath = getBinPath('gocode');
 			if (!path.isAbsolute(toolBinPath)) {
 				return '';
 			}
 			try {
 				const execFile = util.promisify(cp.execFile);
-				const { stderr } = await execFile(toolBinPath, ['close']);
+				const { stderr } = await execFile(toolBinPath, ['close'], {env, timeout: 10000});  // give 10sec.
 				if (stderr.indexOf(`rpc: can't find service Server.`) > -1) {
 					return `Installing gocode aborted as existing process cannot be closed. Please kill the running process for gocode and try again.`;
 				}
 			} catch (err) {
 				// This may fail if gocode isn't already running.
+				console.log(`gocode close failed: ${err}`);
 			}
 			return '';
 		},