src/goMain: export a small API

Exports a function for use by other extensions. When I'm creating a
Go-related VSCode extension, being able to reuse this extension's
configuration and certain helper functions would be very useful.
Additionally, users expect Go-related extensions to respect `go.*`
configuration options, and have reported issues when they don't. This
change exports `getBinPath`. With this function, Go-related
extensions don't have to reinvent the wheel when it comes to
installing and configuring Go tools.

Updates golang/vscode-go#233

Change-Id: I9edf7f87437492182e8562aa107b643ca01a1202
GitHub-Last-Rev: 0171541d958246fc59056e4eba75cd4aa940976f
GitHub-Pull-Request: golang/vscode-go#1642
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/336509
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Trust: Suzy Mueller <suzmue@golang.org>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/src/export.d.ts b/src/export.d.ts
new file mode 100644
index 0000000..5879026
--- /dev/null
+++ b/src/export.d.ts
@@ -0,0 +1,24 @@
+/*---------------------------------------------------------
+ * Copyright 2021 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import { Uri } from 'vscode';
+export { ToolAtVersion } from './goTools';
+
+export interface CommandInvocation {
+	binPath: string;
+	args?: string[];
+	env?: Object;
+	cwd?: string;
+}
+
+export interface ExtensionAPI {
+	settings: {
+		/**
+		 * Returns the execution command corresponding to the specified resource, taking into account
+		 * any workspace-specific settings for the workspace to which this resource belongs.
+		 */
+		getExecutionCommand(toolName: string, resource?: Uri): CommandInvocation | undefined;
+	};
+}
diff --git a/src/extensionAPI.ts b/src/extensionAPI.ts
new file mode 100644
index 0000000..accc455
--- /dev/null
+++ b/src/extensionAPI.ts
@@ -0,0 +1,19 @@
+/*---------------------------------------------------------
+ * Copyright 2021 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import { Uri } from 'vscode';
+import { CommandInvocation, ExtensionAPI } from './export';
+import { getBinPathWithExplanation } from './util';
+
+const api: ExtensionAPI = {
+	settings: {
+		getExecutionCommand(toolName: string, resource?: Uri): CommandInvocation | undefined {
+			const { binPath } = getBinPathWithExplanation(toolName, true, resource);
+			return { binPath };
+		}
+	}
+};
+
+export default api;
diff --git a/src/goMain.ts b/src/goMain.ts
index 99cd264..541ad64 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -112,6 +112,8 @@
 import vscode = require('vscode');
 import { getFormatTool } from './goFormat';
 import { resetSurveyConfig, showSurveyConfig, timeMinute } from './goSurvey';
+import { ExtensionAPI } from './export';
+import extensionAPI from './extensionAPI';
 
 export let buildDiagnosticCollection: vscode.DiagnosticCollection;
 export let lintDiagnosticCollection: vscode.DiagnosticCollection;
@@ -124,7 +126,7 @@
 	return;
 };
 
-export async function activate(ctx: vscode.ExtensionContext) {
+export async function activate(ctx: vscode.ExtensionContext): Promise<ExtensionAPI> {
 	if (process.env['VSCODE_GO_IN_TEST'] === '1') {
 		// Make sure this does not run when running in test.
 		return;
@@ -705,6 +707,8 @@
 	vscode.languages.setLanguageConfiguration(GO_MODE.language, {
 		wordPattern: /(-?\d*\.\d\w*)|([^`~!@#%^&*()\-=+[{\]}\\|;:'",.<>/?\s]+)/g
 	});
+
+	return extensionAPI;
 }
 
 function showGoWelcomePage(ctx: vscode.ExtensionContext) {
diff --git a/src/util.ts b/src/util.ts
index 28270cf..2a35ddf 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -518,8 +518,12 @@
 
 // getBinPathWithExplanation returns the path to the tool, and the explanation on why
 // the path was chosen. See getBinPathWithPreferredGopathGorootWithExplanation for details.
-export function getBinPathWithExplanation(tool: string, useCache = true): { binPath: string; why?: string } {
-	const cfg = getGoConfig();
+export function getBinPathWithExplanation(
+	tool: string,
+	useCache = true,
+	uri?: vscode.Uri
+): { binPath: string; why?: string } {
+	const cfg = getGoConfig(uri);
 	const alternateTools: { [key: string]: string } = cfg.get('alternateTools');
 	const alternateToolPath: string = alternateTools[tool];