src/config: remove WrappedConfiguration in favor of trusted workspace

Most of the code in config.ts was introduced as a stop-gap
before trusted workspace APIs became available. It's now
available, and our extension requires newer vscode engines.
It's time to remove this old hack. Bye!

Change-Id: Ic8e74178f09669f29490237bda0d745f867e7176
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/347690
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Trust: Suzy Mueller <suzmue@golang.org>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Suzy Mueller <suzmue@golang.org>
diff --git a/src/config.ts b/src/config.ts
index 56ba585..28efd4d 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -5,172 +5,6 @@
  *--------------------------------------------------------*/
 
 import vscode = require('vscode');
-import { getFromWorkspaceState, updateWorkspaceState } from './stateUtils';
-
-const WORKSPACE_IS_TRUSTED_KEY = 'WORKSPACE_IS_TRUSTED_KEY';
-const SECURITY_SENSITIVE_CONFIG: string[] = [
-	'alternateTools',
-	'gopath',
-	'goroot',
-	'inferGopath',
-	'toolsGopath',
-	'toolsEnvVars'
-];
-
-// Set true only if the vscode is the recent version that has the workspace trust API AND
-// if the security.workspace.trust is enabled. Change of this configuration requires restart
-// of VSCode, so we don't need to set up the configuration change listener.
-// TODO(hyangah): remove this and Configuration & WrappedConfiguration when we update
-// our extension to require 2021 June VSCode engine.
-const isVscodeWorkspaceTrustAPIAvailable =
-	'boolean' === typeof (vscode.workspace as any).isTrusted &&
-	vscode.workspace.getConfiguration('security.workspace.trust')?.get('enabled') === true;
-
-// Initialize the singleton defaultConfig and register related commands.
-// Prompt if workspace configuration was found but had to be ignored until
-// the user has to explicitly opt in to trust the workspace.
-export async function initConfig(ctx: vscode.ExtensionContext) {
-	ctx.subscriptions.push(vscode.commands.registerCommand('go.workspace.isTrusted.toggle', toggleWorkspaceIsTrusted));
-
-	if (isVscodeWorkspaceTrustAPIAvailable) {
-		return; // let vscode handle configuration management.
-	}
-
-	const isTrusted = getFromWorkspaceState(WORKSPACE_IS_TRUSTED_KEY, false);
-	if (isTrusted !== defaultConfig.workspaceIsTrusted()) {
-		defaultConfig.toggleWorkspaceIsTrusted();
-	}
-
-	if (isTrusted) {
-		return;
-	}
-	const ignored = ignoredWorkspaceConfig(vscode.workspace.getConfiguration('go'), SECURITY_SENSITIVE_CONFIG);
-	if (ignored.length === 0) {
-		return;
-	}
-	const ignoredSettings = ignored.map((x) => `"go.${x}"`).join(',');
-	const val = await vscode.window.showWarningMessage(
-		`Some workspace/folder-level settings (${ignoredSettings}) from the untrusted workspace are disabled ` +
-			'by default. If this workspace is trusted, explicitly enable the workspace/folder-level settings ' +
-			'by running the "Go: Toggle Workspace Trust Flag" command.',
-		'OK',
-		'Trust This Workspace',
-		'More Info'
-	);
-	switch (val) {
-		case 'Trust This Workspace':
-			await toggleWorkspaceIsTrusted();
-			break;
-		case 'More Info':
-			vscode.env.openExternal(
-				vscode.Uri.parse('https://github.com/golang/vscode-go/blob/master/docs/settings.md#security')
-			);
-			break;
-		default:
-			break;
-	}
-}
-
-function ignoredWorkspaceConfig(cfg: vscode.WorkspaceConfiguration, keys: string[]) {
-	return keys.filter((key) => {
-		const inspect = cfg.inspect(key);
-		return inspect.workspaceValue !== undefined || inspect.workspaceFolderValue !== undefined;
-	});
-}
-
-async function toggleWorkspaceIsTrusted() {
-	if (isVscodeWorkspaceTrustAPIAvailable) {
-		vscode.commands.executeCommand('workbench.action.manageTrust');
-		return;
-	}
-	const v = defaultConfig.toggleWorkspaceIsTrusted();
-	await updateWorkspaceState(WORKSPACE_IS_TRUSTED_KEY, v);
-}
-
-// Go extension configuration for a workspace.
-export class Configuration {
-	constructor(private _workspaceIsTrusted = false, private getConfiguration = vscode.workspace.getConfiguration) {}
-
-	public toggleWorkspaceIsTrusted() {
-		this._workspaceIsTrusted = !this._workspaceIsTrusted;
-		return this._workspaceIsTrusted;
-	}
-
-	// returns a Proxied vscode.WorkspaceConfiguration, which prevents
-	// from using the workspace configuration if the workspace is untrusted.
-	public get(section: string, uri?: vscode.Uri): vscode.WorkspaceConfiguration {
-		const cfg = this.getConfiguration(section, uri);
-		if (section !== 'go' || this._workspaceIsTrusted) {
-			return cfg;
-		}
-		return new WrappedConfiguration(cfg);
-	}
-
-	public workspaceIsTrusted(): boolean {
-		return this._workspaceIsTrusted;
-	}
-}
-
-class vscodeConfiguration {
-	public toggleWorkspaceIsTrusted() {
-		/* no-op */
-	}
-	public get(section: string, uri?: vscode.Uri): vscode.WorkspaceConfiguration {
-		return vscode.workspace.getConfiguration(section, uri);
-	}
-	public workspaceIsTrusted(): boolean {
-		return !!(vscode.workspace as any).isTrusted;
-	}
-}
-
-const defaultConfig = isVscodeWorkspaceTrustAPIAvailable ? new vscodeConfiguration() : new Configuration();
-
-// Returns the workspace Configuration used by the extension.
-export function DefaultConfig() {
-	return defaultConfig;
-}
-
-// wrappedConfiguration wraps vscode.WorkspaceConfiguration.
-class WrappedConfiguration implements vscode.WorkspaceConfiguration {
-	constructor(private readonly _wrapped: vscode.WorkspaceConfiguration) {
-		// set getters for direct setting access (e.g. cfg.gopath), but don't overwrite _wrapped.
-		const desc = Object.getOwnPropertyDescriptors(_wrapped);
-		for (const prop in desc) {
-			// TODO(hyangah): find a better way to exclude WrappedConfiguration's members.
-			// These methods are defined by WrappedConfiguration.
-			if (typeof prop === 'string' && !['get', 'has', 'inspect', 'update', '_wrapped'].includes(prop)) {
-				const d = desc[prop];
-				if (SECURITY_SENSITIVE_CONFIG.includes(prop)) {
-					const inspect = this._wrapped.inspect(prop);
-					d.value = inspect.globalValue ?? inspect.defaultValue;
-				}
-				Object.defineProperty(this, prop, desc[prop]);
-			}
-		}
-	}
-
-	public get(section: any, defaultValue?: any) {
-		if (SECURITY_SENSITIVE_CONFIG.includes(section)) {
-			const inspect = this._wrapped.inspect(section);
-			return inspect.globalValue ?? defaultValue ?? inspect.defaultValue;
-		}
-		return this._wrapped.get(section, defaultValue);
-	}
-	public has(section: string) {
-		return this._wrapped.has(section);
-	}
-	public inspect<T>(section: string) {
-		return this._wrapped.inspect<T>(section);
-	}
-	public update(
-		section: string,
-		value: any,
-		configurationTarget?: boolean | vscode.ConfigurationTarget,
-		overrideInLanguage?: boolean
-	): Thenable<void> {
-		return this._wrapped.update(section, value, configurationTarget, overrideInLanguage);
-	}
-}
 
 // getGoConfig is declared as an exported const rather than a function, so it can be stubbbed in testing.
 export const getGoConfig = (uri?: vscode.Uri) => {
@@ -190,7 +24,7 @@
 			uri = null;
 		}
 	}
-	return defaultConfig.get(section, uri);
+	return vscode.workspace.getConfiguration(section, uri);
 }
 
 // True if the extension is running in known cloud-based IDEs.
diff --git a/src/goMain.ts b/src/goMain.ts
index 941b693..b6f8d2a 100644
--- a/src/goMain.ts
+++ b/src/goMain.ts
@@ -9,7 +9,7 @@
 'use strict';
 
 import * as path from 'path';
-import { getGoConfig, getGoplsConfig, initConfig, IsInCloudIDE } from './config';
+import { getGoConfig, getGoplsConfig, IsInCloudIDE } from './config';
 import { browsePackages } from './goBrowsePackage';
 import { buildCode } from './goBuild';
 import { check, notifyIfGeneratedFile, removeTestStatus } from './goCheck';
@@ -138,8 +138,6 @@
 	setWorkspaceState(ctx.workspaceState);
 	setEnvironmentVariableCollection(ctx.environmentVariableCollection);
 
-	await initConfig(ctx);
-
 	const cfg = getGoConfig();
 	setLogConfig(cfg['logging']);
 
diff --git a/src/util.ts b/src/util.ts
index 2a35ddf..35eab17 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -12,7 +12,7 @@
 import util = require('util');
 import vscode = require('vscode');
 import { NearestNeighborDict, Node } from './avlTree';
-import { DefaultConfig, getGoConfig } from './config';
+import { getGoConfig } from './config';
 import { extensionId } from './const';
 import { toolExecutionEnvironment } from './goEnv';
 import { languageClient } from './goLanguageServer';
@@ -495,7 +495,7 @@
 		return toolsGopathForWorkspace;
 	}
 
-	if (DefaultConfig().workspaceIsTrusted() === false) {
+	if (!vscode.workspace.isTrusted) {
 		return toolsGopathForWorkspace;
 	}
 
diff --git a/test/integration/config.test.ts b/test/integration/config.test.ts
deleted file mode 100644
index 525b42d..0000000
--- a/test/integration/config.test.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-vars */
-/* eslint-disable @typescript-eslint/no-explicit-any */
-/*---------------------------------------------------------
- * Copyright 2021 The Go Authors. All rights reserved.
- * Licensed under the MIT License. See LICENSE in the project root for license information.
- *--------------------------------------------------------*/
-
-'use strict';
-
-import * as assert from 'assert';
-import { Configuration } from '../../src/config';
-import { MockCfg } from '../mocks/MockCfg';
-
-suite('GoConfiguration Tests', () => {
-	function check(trusted: boolean, workspaceConfig: { [key: string]: any }, key: string, expected: any) {
-		const getConfigurationFn = (section: string) => new MockCfg(workspaceConfig);
-		const cfg = new Configuration(trusted, getConfigurationFn).get('go');
-
-		const got0 = JSON.stringify(cfg.get(key));
-		const got1 = JSON.stringify(cfg[key]);
-		const want = JSON.stringify(expected);
-		assert.strictEqual(got0, want, `cfg.get(${key}) = ${got0}, want ${want}`);
-		assert.strictEqual(got1, want, `cfg[${key}] = ${got1}, want ${want}`);
-	}
-
-	test('trusted workspace accepts all workspace settings', () => {
-		check(true, { goroot: 'goroot_val' }, 'goroot', 'goroot_val');
-		check(true, { gopath: 'gopath_val' }, 'gopath', 'gopath_val');
-		check(true, { toolsGopath: 'toolsGopath_val' }, 'toolsGopath', 'toolsGopath_val');
-		check(true, { alternateTools: { go: 'foo' } }, 'alternateTools', { go: 'foo' });
-		check(true, { inferGopath: true }, 'inferGopath', true);
-
-		check(true, { buildFlags: ['-v'] }, 'buildFlags', ['-v']);
-		check(true, { languageServerFlags: ['-rpc.trace'] }, 'languageServerFlags', ['-rpc.trace']);
-	});
-
-	test('untrusted workspace ignores dangerous settings', () => {
-		check(false, { goroot: 'goroot_val' }, 'goroot', null);
-		check(false, { gopath: 'gopath_val' }, 'gopath', null);
-		check(false, { toolsGopath: 'toolsGopath_val' }, 'toolsGopath', null);
-		check(false, { alternateTools: { go: 'foo' } }, 'alternateTools', {});
-		check(false, { inferGopath: true }, 'inferGopath', false);
-
-		check(false, { buildFlags: ['-v'] }, 'buildFlags', ['-v']);
-		check(false, { languageServerFlags: ['-rpc.trace'] }, 'languageServerFlags', ['-rpc.trace']);
-	});
-
-	function checkGopls(trusted: boolean, workspaceConfig: { [key: string]: any }, key: string, expected: any) {
-		const getConfigurationFn = (section: string) => new MockCfg(workspaceConfig);
-		const cfg = new Configuration(trusted, getConfigurationFn).get('gopls');
-
-		const got0 = JSON.stringify(cfg.get(key));
-		const got1 = JSON.stringify(cfg[key]);
-		const want = JSON.stringify(expected);
-		assert.strictEqual(got0, want, `cfg.get(${key}) = ${got0}, want ${want}`);
-		assert.strictEqual(got1, want, `cfg[${key}] = ${got1}, want ${want}`);
-	}
-
-	test('trusted workspace (gopls settings) accepts all settings', () => {
-		// unaffected settings.
-		checkGopls(true, { buildFlags: '-v' }, 'buildFlags', '-v');
-		checkGopls(true, { env: { GOBIN: 'foo' } }, 'env', { GOBIN: 'foo' });
-	});
-
-	test('untrusted workspace (gopls settings) ignores dangerous settings', () => {
-		// unaffected settings
-		checkGopls(false, { buildFlags: '-v' }, 'buildFlags', '-v');
-		checkGopls(false, { env: { GOBIN: 'foo' } }, 'env', { GOBIN: 'foo' });
-	});
-});