[vscode-go] src/misc: fix strict type errors in various commands and data providers

68 views
Skip to first unread message

Jamal Carvalho (Gerrit)

unread,
Apr 22, 2022, 3:10:22 PM4/22/22
to goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

View Change

    To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: vscode-go
    Gerrit-Branch: master
    Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
    Gerrit-Change-Number: 401620
    Gerrit-PatchSet: 3
    Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
    Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
    Gerrit-Comment-Date: Fri, 22 Apr 2022 19:10:18 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    kokoro (Gerrit)

    unread,
    Apr 22, 2022, 3:17:20 PM4/22/22
    to Jamal Carvalho, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

    Attention is currently required from: Jamal Carvalho.

    Kokoro presubmit build finished with status: FAILURE
    Logs at: https://source.cloud.google.com/results/invocations/be801264-b8ea-4257-b8b2-fe571c3bbd1f

    Patch set 3:TryBot-Result -1

    View Change

      To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: vscode-go
      Gerrit-Branch: master
      Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
      Gerrit-Change-Number: 401620
      Gerrit-PatchSet: 3
      Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
      Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
      Gerrit-Reviewer: kokoro <noreply...@google.com>
      Gerrit-Attention: Jamal Carvalho <ja...@golang.org>
      Gerrit-Comment-Date: Fri, 22 Apr 2022 19:17:17 +0000
      Gerrit-HasComments: No
      Gerrit-Has-Labels: Yes
      Gerrit-MessageType: comment

      Jamal Carvalho (Gerrit)

      unread,
      Apr 23, 2022, 6:02:40 PM4/23/22
      to goph...@pubsubhelper.golang.org, kokoro, golang-co...@googlegroups.com

      View Change

        To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: vscode-go
        Gerrit-Branch: master
        Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
        Gerrit-Change-Number: 401620
        Gerrit-PatchSet: 4
        Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
        Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
        Gerrit-Reviewer: kokoro <noreply...@google.com>
        Gerrit-Comment-Date: Sat, 23 Apr 2022 22:02:36 +0000

        kokoro (Gerrit)

        unread,
        Apr 23, 2022, 6:18:43 PM4/23/22
        to Jamal Carvalho, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

        Kokoro presubmit build finished with status: SUCCESS
        Logs at: https://source.cloud.google.com/results/invocations/98c8cd07-e80c-4aeb-9a12-f76655096c17

        Patch set 4:TryBot-Result +1

        View Change

          To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: vscode-go
          Gerrit-Branch: master
          Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
          Gerrit-Change-Number: 401620
          Gerrit-PatchSet: 4
          Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
          Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
          Gerrit-Reviewer: kokoro <noreply...@google.com>
          Gerrit-Comment-Date: Sat, 23 Apr 2022 22:18:39 +0000

          kokoro (Gerrit)

          unread,
          Apr 29, 2022, 9:59:22 AM4/29/22
          to Jamal Carvalho, goph...@pubsubhelper.golang.org, Hyang-Ah Hana Kim, golang-co...@googlegroups.com

          Attention is currently required from: Hyang-Ah Hana Kim, Jamal Carvalho.

          Kokoro presubmit build finished with status: SUCCESS

          Logs at: https://source.cloud.google.com/results/invocations/b6ac377d-9039-4271-bc61-c556ccc70b39

          Patch set 6:TryBot-Result +1

          View Change

            To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: vscode-go
            Gerrit-Branch: master
            Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
            Gerrit-Change-Number: 401620
            Gerrit-PatchSet: 6
            Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
            Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
            Gerrit-Reviewer: kokoro <noreply...@google.com>
            Gerrit-Attention: Jamal Carvalho <ja...@golang.org>
            Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Comment-Date: Fri, 29 Apr 2022 13:59:18 +0000

            Hyang-Ah Hana Kim (Gerrit)

            unread,
            Apr 29, 2022, 5:22:06 PM4/29/22
            to Jamal Carvalho, goph...@pubsubhelper.golang.org, Hyang-Ah Hana Kim, kokoro, golang-co...@googlegroups.com

            Attention is currently required from: Jamal Carvalho.

            Patch set 6:Code-Review +2

            View Change

            1 comment:

            To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: vscode-go
            Gerrit-Branch: master
            Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
            Gerrit-Change-Number: 401620
            Gerrit-PatchSet: 6
            Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
            Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
            Gerrit-Reviewer: kokoro <noreply...@google.com>
            Gerrit-Attention: Jamal Carvalho <ja...@golang.org>
            Gerrit-Comment-Date: Fri, 29 Apr 2022 21:22:01 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: Yes
            Gerrit-MessageType: comment

            Benny Siegert (Gerrit)

            unread,
            May 2, 2022, 1:06:13 PM5/2/22
            to Jamal Carvalho, goph...@pubsubhelper.golang.org, Benny Siegert, Hyang-Ah Hana Kim, kokoro, golang-co...@googlegroups.com

            Attention is currently required from: Jamal Carvalho.

            Patch set 6:Code-Review +1

            View Change

              To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

              Gerrit-Project: vscode-go
              Gerrit-Branch: master
              Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
              Gerrit-Change-Number: 401620
              Gerrit-PatchSet: 6
              Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
              Gerrit-Reviewer: Benny Siegert <bsie...@gmail.com>
              Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
              Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
              Gerrit-Reviewer: kokoro <noreply...@google.com>
              Gerrit-Attention: Jamal Carvalho <ja...@golang.org>
              Gerrit-Comment-Date: Mon, 02 May 2022 17:06:08 +0000

              kokoro (Gerrit)

              unread,
              May 2, 2022, 5:05:06 PM5/2/22
              to Jamal Carvalho, goph...@pubsubhelper.golang.org, Benny Siegert, Hyang-Ah Hana Kim, golang-co...@googlegroups.com

              Attention is currently required from: Jamal Carvalho.

              Kokoro presubmit build finished with status: SUCCESS
              Logs at: https://source.cloud.google.com/results/invocations/6fb42dd3-19ee-4987-bdfa-8baed285efe9

              Patch set 7:TryBot-Result +1

              View Change

                To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

                Gerrit-Project: vscode-go
                Gerrit-Branch: master
                Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
                Gerrit-Change-Number: 401620
                Gerrit-PatchSet: 7
                Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
                Gerrit-Reviewer: Benny Siegert <bsie...@gmail.com>
                Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
                Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
                Gerrit-Reviewer: kokoro <noreply...@google.com>
                Gerrit-Attention: Jamal Carvalho <ja...@golang.org>
                Gerrit-Comment-Date: Mon, 02 May 2022 21:05:02 +0000

                Jamal Carvalho (Gerrit)

                unread,
                May 3, 2022, 9:34:55 AM5/3/22
                to goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, kokoro, Benny Siegert, Hyang-Ah Hana Kim, golang-co...@googlegroups.com

                Jamal Carvalho submitted this change.

                View Change



                6 is the latest approved patch-set.
                No files were changed between the latest approved patch-set and the submitted one.

                Approvals: Hyang-Ah Hana Kim: Looks good to me, approved Jamal Carvalho: Run TryBots Benny Siegert: Looks good to me, but someone else must approve kokoro: TryBots succeeded
                src/misc: fix strict type errors in various commands and data providers

                For golang/vscode-go#57.

                Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
                Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/401620
                Run-TryBot: Jamal Carvalho <ja...@golang.org>
                Reviewed-by: Benny Siegert <bsie...@gmail.com>
                TryBot-Result: kokoro <noreply...@google.com>
                Reviewed-by: Hyang-Ah Hana Kim <hya...@gmail.com>
                ---
                M src/goBuild.ts
                M src/goCover.ts
                M src/goDebugConfiguration.ts
                M src/goDebugFactory.ts
                M src/goDeveloperSurvey.ts
                M src/goEnv.ts
                M src/goEnvironmentStatus.ts
                M src/goExplorer.ts
                M src/goFillStruct.ts
                M src/goGenerateTests.ts
                M src/goGetPackage.ts
                M src/goImpl.ts
                M src/goImport.ts
                M src/goInstall.ts
                M src/goInstallTools.ts
                M src/goLint.ts
                M src/goMain.ts
                M src/goMode.ts
                M src/goModifytags.ts
                M src/goModules.ts
                M src/goPackages.ts
                M src/goPlayground.ts
                M src/goStatus.ts
                M src/goSurvey.ts
                M src/goTest.ts
                M src/goTools.ts
                M src/goVet.ts
                M src/goVulncheck.ts
                28 files changed, 227 insertions(+), 175 deletions(-)

                diff --git a/src/goBuild.ts b/src/goBuild.ts
                index b1bc108..fdcfea6 100644
                --- a/src/goBuild.ts
                +++ b/src/goBuild.ts
                @@ -41,7 +41,7 @@
                }
                }

                - const documentUri = editor ? editor.document.uri : null;
                + const documentUri = editor?.document.uri;
                const goConfig = getGoConfig(documentUri);

                outputChannel.clear(); // Ensures stale output from build on save is cleared
                @@ -51,7 +51,7 @@
                isModSupported(documentUri).then((isMod) => {
                goBuild(documentUri, isMod, goConfig, buildWorkspace)
                .then((errors) => {
                - handleDiagnosticErrors(editor ? editor.document : null, errors, buildDiagnosticCollection);
                + handleDiagnosticErrors(editor?.document, errors, buildDiagnosticCollection);
                diagnosticsStatusBarItem.hide();
                })
                .catch((err) => {
                @@ -70,7 +70,7 @@
                * @param buildWorkspace If true builds code in all workspace.
                */
                export async function goBuild(
                - fileUri: vscode.Uri,
                + fileUri: vscode.Uri | undefined,
                isMod: boolean,
                goConfig: vscode.WorkspaceConfiguration,
                buildWorkspace?: boolean
                @@ -91,13 +91,14 @@
                };

                const currentWorkspace = getWorkspaceFolderPath(fileUri);
                - const cwd = buildWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);
                + const cwd = buildWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri?.fsPath ?? '');
                if (!path.isAbsolute(cwd)) {
                return Promise.resolve([]);
                }

                // Skip building if cwd is in the module cache
                - if (isMod && cwd.startsWith(getModuleCache())) {
                + const cache = getModuleCache();
                + if (isMod && cache && cwd.startsWith(cache)) {
                return [];
                }

                @@ -133,7 +134,7 @@
                currentWorkspace,
                'error',
                true,
                - null,
                + '',
                buildEnv,
                true,
                tokenSource.token
                @@ -162,10 +163,10 @@
                running = true;
                return runTool(
                buildArgs.concat('-o', tmpPath, importPath),
                - cwd,
                + cwd ?? '',
                'error',
                true,
                - null,
                + '',
                buildEnv,
                true,
                tokenSource.token
                diff --git a/src/goCover.ts b/src/goCover.ts
                index b645f09..d2f8bcc 100644
                --- a/src/goCover.ts
                +++ b/src/goCover.ts
                @@ -213,7 +213,7 @@
                * @param packageDirPath Absolute path of the package for which the coverage was calculated
                * @param dir Directory to execute go list in
                */
                -export function applyCodeCoverageToAllEditors(coverProfilePath: string, dir: string): Promise<void> {
                +export function applyCodeCoverageToAllEditors(coverProfilePath: string, dir?: string): Promise<void> {
                const v = new Promise<void>((resolve, reject) => {
                try {
                const showCounts = getGoConfig().get('coverShowCounts') as boolean;
                @@ -285,7 +285,7 @@
                resolve();
                });
                } catch (e) {
                - vscode.window.showInformationMessage(e.msg);
                + vscode.window.showInformationMessage((e as any).msg);
                reject(e);
                }
                });
                @@ -358,7 +358,7 @@
                * Apply the code coverage highlighting in given editor
                * @param editor
                */
                -export function applyCodeCoverage(editor: vscode.TextEditor) {
                +export function applyCodeCoverage(editor: vscode.TextEditor | undefined) {
                if (!editor || editor.document.languageId !== 'go' || editor.document.fileName.endsWith('_test.go')) {
                return;
                }
                diff --git a/src/goDebugConfiguration.ts b/src/goDebugConfiguration.ts
                index 97fafeb..8e5f346 100644
                --- a/src/goDebugConfiguration.ts
                +++ b/src/goDebugConfiguration.ts
                @@ -121,7 +121,7 @@
                folder: vscode.WorkspaceFolder | undefined,
                debugConfiguration: vscode.DebugConfiguration,
                token?: vscode.CancellationToken
                - ): Promise<vscode.DebugConfiguration> {
                + ): Promise<vscode.DebugConfiguration | undefined> {
                const activeEditor = vscode.window.activeTextEditor;
                if (!debugConfiguration || !debugConfiguration.request) {
                // if 'request' is missing interpret this as a missing launch.json
                @@ -155,14 +155,14 @@

                const goConfig = getGoConfig(folder && folder.uri);
                const dlvConfig = goConfig['delveConfig'];
                - const defaultConfig = vscode.extensions.getExtension(extensionId).packageJSON.contributes.configuration
                + const defaultConfig = vscode.extensions.getExtension(extensionId)?.packageJSON.contributes.configuration
                .properties['go.delveConfig'].properties;

                // Figure out which debugAdapter is being used first, so we can use this to send warnings
                // for properties that don't apply.
                // If debugAdapter is not provided in launch.json, see if it's in settings.json.
                if (!debugConfiguration.hasOwnProperty('debugAdapter') && dlvConfig.hasOwnProperty('debugAdapter')) {
                - const { globalValue, workspaceValue } = goConfig.inspect('delveConfig.debugAdapter');
                + const { globalValue, workspaceValue } = goConfig.inspect('delveConfig.debugAdapter') ?? {};
                // user configured the default debug adapter through settings.json.
                if (globalValue !== undefined || workspaceValue !== undefined) {
                debugConfiguration['debugAdapter'] = dlvConfig['debugAdapter'];
                @@ -206,8 +206,8 @@
                if (
                debugAdapter === 'dlv-dap' &&
                (debugConfiguration.hasOwnProperty('dlvLoadConfig') ||
                - goConfig.inspect('delveConfig.dlvLoadConfig').globalValue !== undefined ||
                - goConfig.inspect('delveConfig.dlvLoadConfig').workspaceValue !== undefined)
                + goConfig.inspect('delveConfig.dlvLoadConfig')?.globalValue !== undefined ||
                + goConfig.inspect('delveConfig.dlvLoadConfig')?.workspaceValue !== undefined)
                ) {
                this.showWarning(
                'ignoreDebugDlvConfigWithDlvDapWarning',
                @@ -240,7 +240,7 @@

                if (debugAdapter !== 'dlv-dap' && debugConfiguration.request === 'attach' && !debugConfiguration['cwd']) {
                debugConfiguration['cwd'] = '${workspaceFolder}';
                - if (vscode.workspace.workspaceFolders?.length > 1) {
                + if (vscode.workspace.workspaceFolders?.length ?? 0 > 1) {
                debugConfiguration['cwd'] = '${fileWorkspaceFolder}';
                }
                }
                @@ -394,7 +394,7 @@
                folder: vscode.WorkspaceFolder | undefined,
                debugConfiguration: vscode.DebugConfiguration,
                token?: vscode.CancellationToken
                - ): vscode.DebugConfiguration {
                + ): vscode.DebugConfiguration | null {
                const debugAdapter = debugConfiguration['debugAdapter'];
                if (debugAdapter === '') {
                return null;
                diff --git a/src/goDebugFactory.ts b/src/goDebugFactory.ts
                index 4ea35bf..fe83cfe 100644
                --- a/src/goDebugFactory.ts
                +++ b/src/goDebugFactory.ts
                @@ -218,13 +218,13 @@
                // VSCode and a dlv dap process spawned and managed by this adapter.
                // It turns the process's stdout/stderrr into OutputEvent.
                export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
                - constructor(private configuration: vscode.DebugConfiguration, logger?: Logger) {
                + constructor(private configuration: vscode.DebugConfiguration, logger: Logger) {
                super(logger);
                }

                - private connected: Promise<{ connected: boolean; reason?: any }>;
                - private dlvDapServer: ChildProcess;
                - private socket: net.Socket;
                + private connected?: Promise<{ connected: boolean; reason?: any }>;
                + private dlvDapServer?: ChildProcess;
                + private socket?: net.Socket;
                private terminatedOnError = false;

                protected sendMessageToClient(message: vscode.DebugProtocolMessage) {
                @@ -290,9 +290,6 @@
                }
                this.connected = undefined;

                - if (timeoutMS === undefined || timeoutMS < 0) {
                - timeoutMS = 1_000;
                - }
                const dlvDapServer = this.dlvDapServer;
                this.dlvDapServer = undefined;
                if (!dlvDapServer) {
                @@ -305,6 +302,9 @@
                return;
                }
                await new Promise<void>((resolve) => {
                + if (timeoutMS === undefined || timeoutMS < 0) {
                + timeoutMS = 1_000;
                + }
                const exitTimeoutToken = setTimeout(() => {
                this.logger?.error(`dlv dap process (${dlvDapServer.pid}) isn't responding. Killing...`);
                dlvDapServer.kill('SIGINT'); // Don't use treekill but let dlv handle cleaning up the child processes.
                @@ -341,7 +341,7 @@

                async startDapServer(
                configuration: vscode.DebugConfiguration
                - ): Promise<{ dlvDapServer?: ChildProcessWithoutNullStreams; socket: net.Socket }> {
                + ): Promise<{ dlvDapServer?: ChildProcess; socket: net.Socket }> {
                const log = (msg: string) => this.outputEvent('stdout', msg);
                const logErr = (msg: string) => this.outputEvent('stderr', msg);
                const logConsole = (msg: string) => {
                @@ -450,7 +450,8 @@

                function waitForDAPServer(port: number, timeoutMs: number): Promise<net.Socket> {
                return new Promise((resolve, reject) => {
                - let s: net.Server = undefined;
                + // eslint-disable-next-line prefer-const
                + let s: net.Server | undefined;
                const timeoutToken = setTimeout(() => {
                if (s?.listening) {
                s.close();
                @@ -463,7 +464,7 @@
                `connected: ${port} (remote: ${socket.remoteAddress}:${socket.remotePort} local: ${socket.localAddress}:${socket.localPort})`
                );
                clearTimeout(timeoutToken);
                - s.close(); // accept no more connection
                + s?.close(); // accept no more connection
                socket.resume();
                resolve(socket);
                });
                diff --git a/src/goDeveloperSurvey.ts b/src/goDeveloperSurvey.ts
                index a18e9c1..ec942e8 100644
                --- a/src/goDeveloperSurvey.ts
                +++ b/src/goDeveloperSurvey.ts
                @@ -58,7 +58,7 @@
                setTimeout(callback, 5 * timeMinute);
                return;
                }
                - cfg = await promptForDeveloperSurvey(cfg, now);
                + cfg = await promptForDeveloperSurvey(cfg ?? {}, now);
                if (cfg) {
                flushSurveyConfig(developerSurveyConfig, cfg);
                }
                @@ -69,7 +69,7 @@
                // shouldPromptForSurvey decides if we should prompt the given user to take the
                // survey. It returns the DeveloperSurveyConfig if we should prompt, and
                // undefined if we should not prompt.
                -export function shouldPromptForSurvey(now: Date, cfg: DeveloperSurveyConfig): DeveloperSurveyConfig {
                +export function shouldPromptForSurvey(now: Date, cfg: DeveloperSurveyConfig): DeveloperSurveyConfig | undefined {
                // TODO(rstambler): Merge checks for surveys into a setting.

                // Don't prompt if the survey hasn't started or is over.
                diff --git a/src/goEnv.ts b/src/goEnv.ts
                index 59a7565..aebd903 100644
                --- a/src/goEnv.ts
                +++ b/src/goEnv.ts
                @@ -36,7 +36,7 @@
                break;
                }
                });
                - return;
                + return {};
                }
                env['GOPATH'] = toolsGopath;

                diff --git a/src/goEnvironmentStatus.ts b/src/goEnvironmentStatus.ts
                index 466f7c4..7328326 100644
                --- a/src/goEnvironmentStatus.ts
                +++ b/src/goEnvironmentStatus.ts
                @@ -38,7 +38,7 @@
                }
                }

                -export let terminalCreationListener: vscode.Disposable;
                +export let terminalCreationListener: vscode.Disposable | undefined;

                let environmentVariableCollection: vscode.EnvironmentVariableCollection;
                export function setEnvironmentVariableCollection(env: vscode.EnvironmentVariableCollection) {
                @@ -79,7 +79,7 @@
                }

                // fetch default go and uninstalled go versions
                - let defaultOption: GoEnvironmentOption;
                + let defaultOption: GoEnvironmentOption | undefined;
                let uninstalledOptions: GoEnvironmentOption[];
                let goSDKOptions: GoEnvironmentOption[];
                try {
                @@ -89,7 +89,7 @@
                getSDKGoOptions()
                ]);
                } catch (e) {
                - vscode.window.showErrorMessage(e.message);
                + vscode.window.showErrorMessage((e as Error).message);
                return;
                }

                @@ -123,7 +123,7 @@
                try {
                await setSelectedGo(selection);
                } catch (e) {
                - vscode.window.showErrorMessage(e.message);
                + vscode.window.showErrorMessage((e as Error).message);
                }
                }

                @@ -163,7 +163,7 @@
                return false;
                }
                const newGoBin = fixDriveCasingInWindows(newGoUris[0].fsPath);
                - const oldGoBin = fixDriveCasingInWindows(path.join(defaultUri.fsPath, correctBinname('go')));
                + const oldGoBin = fixDriveCasingInWindows(path.join(defaultUri?.fsPath ?? '', correctBinname('go')));

                if (newGoBin === oldGoBin) {
                return false;
                @@ -472,7 +472,7 @@
                const dlPath = `golang.org/dl/${result.version}`;
                const label = result.version.replace('go', 'Go ');
                return [...opts, new GoEnvironmentOption(dlPath, label, false)];
                - }, []);
                + }, [] as GoEnvironmentOption[]);
                }

                export const latestGoVersionKey = 'latestGoVersions';
                diff --git a/src/goExplorer.ts b/src/goExplorer.ts
                index b8d503f..8423cc6 100644
                --- a/src/goExplorer.ts
                +++ b/src/goExplorer.ts
                @@ -99,7 +99,7 @@
                if (!uri) {
                return;
                }
                - let pick: { label?: string; description?: string };
                + let pick: { label?: string; description?: string } | undefined;
                if (isEnvTreeItem(item)) {
                pick = { label: item.key, description: item.value };
                } else {
                @@ -114,7 +114,7 @@
                if (!pick) return;
                const { label, description } = pick;
                const value = await vscode.window.showInputBox({ title: label, value: description });
                - if (typeof value !== 'undefined') {
                + if (label && typeof value !== 'undefined') {
                await GoEnv.edit({ [label]: value });
                }
                }
                @@ -140,7 +140,7 @@
                }

                private async envTreeItems(uri?: vscode.Uri) {
                - const env = await this.goEnvCache.get(uri?.toString());
                + const env = await this.goEnvCache.get(uri?.toString() ?? '');
                const items = [];
                for (const [k, v] of Object.entries(env)) {
                if (v !== '') {
                @@ -270,9 +270,9 @@
                contextValue = 'go:explorer:toolitem';
                description = 'not installed';
                label: string;
                - children: vscode.TreeItem[];
                + children?: vscode.TreeItem[];
                collapsibleState?: vscode.TreeItemCollapsibleState;
                - tooltip: string;
                + tooltip?: string;
                constructor({ name, version, goVersion, binPath, error }: ToolDetail) {
                this.label = name;
                if (binPath) {
                @@ -314,7 +314,7 @@
                version: moduleVersion
                };
                } catch (e) {
                - return { name: name, error: e };
                + return { name: name, error: e as Error };
                }
                }

                diff --git a/src/goFillStruct.ts b/src/goFillStruct.ts
                index e4bc1c2..9a2f787 100644
                --- a/src/goFillStruct.ts
                +++ b/src/goFillStruct.ts
                @@ -99,7 +99,7 @@
                }
                });
                if (p.pid) {
                - p.stdin.end(input);
                + p.stdin?.end(input);
                }
                });
                }
                diff --git a/src/goGenerateTests.ts b/src/goGenerateTests.ts
                index b5e02f7..756dca8 100644
                --- a/src/goGenerateTests.ts
                +++ b/src/goGenerateTests.ts
                @@ -69,10 +69,10 @@
                vscode.commands.executeCommand('vscode.open', vscode.Uri.file(targetFilePath));
                }

                -export function generateTestCurrentPackage(): Promise<boolean> {
                +export async function generateTestCurrentPackage(): Promise<boolean> {
                const editor = checkActiveEditor();
                if (!editor) {
                - return;
                + return false;
                }
                return generateTests(
                {
                @@ -83,10 +83,10 @@
                );
                }

                -export function generateTestCurrentFile(): Promise<boolean> {
                +export async function generateTestCurrentFile(): Promise<boolean> {
                const editor = checkActiveEditor();
                if (!editor) {
                - return;
                + return false;
                }

                return generateTests(
                @@ -101,14 +101,12 @@
                export async function generateTestCurrentFunction(): Promise<boolean> {
                const editor = checkActiveEditor();
                if (!editor) {
                - return;
                + return false;
                }

                const functions = await getFunctions(editor.document);
                const selection = editor.selection;
                - const currentFunction: vscode.DocumentSymbol = functions.find(
                - (func) => selection && func.range.contains(selection.start)
                - );
                + const currentFunction = functions.find((func) => selection && func.range.contains(selection.start));

                if (!currentFunction) {
                vscode.window.showInformationMessage('No function found at cursor.');
                @@ -216,8 +214,8 @@

                return resolve(true);
                } catch (e) {
                - vscode.window.showInformationMessage(e.msg);
                - outputChannel.append(e.msg);
                + vscode.window.showInformationMessage((e as any).msg);
                + outputChannel.append((e as any).msg);
                reject(e);
                }
                });
                @@ -226,7 +224,7 @@

                async function getFunctions(doc: vscode.TextDocument): Promise<vscode.DocumentSymbol[]> {
                const documentSymbolProvider = new GoDocumentSymbolProvider();
                - const symbols = await documentSymbolProvider.provideDocumentSymbols(doc, null);
                + const symbols = await documentSymbolProvider.provideDocumentSymbols(doc);
                return symbols[0].children.filter((sym) =>
                [vscode.SymbolKind.Function, vscode.SymbolKind.Method].includes(sym.kind)
                );
                diff --git a/src/goGetPackage.ts b/src/goGetPackage.ts
                index 86e5dc9..6e8ce30 100644
                --- a/src/goGetPackage.ts
                +++ b/src/goGetPackage.ts
                @@ -14,9 +14,8 @@

                export function goGetPackage() {
                const editor = vscode.window.activeTextEditor;
                - const selection = editor.selection;
                - const selectedText = editor.document.lineAt(selection.active.line).text;
                -
                + const selection = editor?.selection;
                + const selectedText = editor?.document.lineAt(selection?.active.line ?? 0).text ?? '';
                const importPath = getImportPath(selectedText);
                if (importPath === '') {
                vscode.window.showErrorMessage('No import path to get');
                diff --git a/src/goImpl.ts b/src/goImpl.ts
                index c9c59f4..dfb7870 100644
                --- a/src/goImpl.ts
                +++ b/src/goImpl.ts
                @@ -70,6 +70,6 @@
                }
                );
                if (p.pid) {
                - p.stdin.end();
                + p.stdin?.end();
                }
                }
                diff --git a/src/goImport.ts b/src/goImport.ts
                index 4a7a062..43d728e 100644
                --- a/src/goImport.ts
                +++ b/src/goImport.ts
                @@ -26,7 +26,9 @@
                excludeImportedPkgs && vscode.window.activeTextEditor
                ? await getImports(vscode.window.activeTextEditor.document)
                : [];
                - const pkgMap = await getImportablePackages(vscode.window.activeTextEditor.document.fileName, true);
                + const pkgMap = vscode.window.activeTextEditor
                + ? await getImportablePackages(vscode.window.activeTextEditor?.document.fileName, true)
                + : new Map();
                const stdLibs: string[] = [];
                const nonStdLibs: string[] = [];
                pkgMap.forEach((value, key) => {
                @@ -46,9 +48,12 @@
                const COMMAND = 'gopls.list_known_packages';
                if (languageClient && serverInfo?.Commands?.includes(COMMAND)) {
                try {
                - const uri = languageClient.code2ProtocolConverter.asTextDocumentIdentifier(
                - vscode.window.activeTextEditor.document
                - ).uri;
                + const editor = vscode.window.activeTextEditor;
                + if (!editor) {
                + vscode.window.showErrorMessage('No active editor found.');
                + return [];
                + }
                + const uri = languageClient.code2ProtocolConverter.asTextDocumentIdentifier(editor.document).uri;
                const params: ExecuteCommandParams = {
                command: COMMAND,
                arguments: [
                @@ -80,7 +85,7 @@
                importsOption: GoOutlineImportsOptions.Only,
                document
                };
                - const symbols = await documentSymbols(options, null);
                + const symbols = await documentSymbols(options);
                if (!symbols || !symbols.length) {
                return [];
                }
                @@ -102,13 +107,18 @@
                }
                }

                -export function getTextEditForAddImport(arg: string): vscode.TextEdit[] {
                +export function getTextEditForAddImport(arg: string | undefined): vscode.TextEdit[] | undefined {
                // Import name wasn't provided
                if (arg === undefined) {
                - return null;
                + return undefined;
                + }
                + const editor = vscode.window.activeTextEditor;
                + if (!editor) {
                + vscode.window.showErrorMessage('No active editor found.');
                + return [];
                }

                - const { imports, pkg } = parseFilePrelude(vscode.window.activeTextEditor.document.getText());
                + const { imports, pkg } = parseFilePrelude(editor.document.getText());
                if (imports.some((block) => block.pkgs.some((pkgpath) => pkgpath === arg))) {
                return [];
                }
                @@ -131,7 +141,7 @@

                edits.push(vscode.TextEdit.insert(new vscode.Position(minusCgo[0].start, 0), 'import (\n\t"' + arg + '"\n'));
                minusCgo.forEach((element) => {
                - const currentLine = vscode.window.activeTextEditor.document.lineAt(element.start).text;
                + const currentLine = editor.document.lineAt(element.start).text;
                const updatedLine = currentLine.replace(/^\s*import\s*/, '\t');
                edits.push(
                vscode.TextEdit.replace(
                @@ -167,9 +177,12 @@
                const COMMAND = 'gopls.add_import';
                if (languageClient && serverInfo?.Commands?.includes(COMMAND)) {
                try {
                - const uri = languageClient.code2ProtocolConverter.asTextDocumentIdentifier(
                - vscode.window.activeTextEditor.document
                - ).uri;
                + const editor = vscode.window.activeTextEditor;
                + if (!editor) {
                + vscode.window.showErrorMessage('No active editor found to determine current package.');
                + return [];
                + }
                + const uri = languageClient.code2ProtocolConverter.asTextDocumentIdentifier(editor.document).uri;
                const params: ExecuteCommandParams = {
                command: COMMAND,
                arguments: [
                diff --git a/src/goInstall.ts b/src/goInstall.ts
                index 71a19b5..aecf947 100644
                --- a/src/goInstall.ts
                +++ b/src/goInstall.ts
                @@ -39,7 +39,8 @@
                const isMod = await isModSupported(editor.document.uri);

                // Skip installing if cwd is in the module cache
                - if (isMod && cwd.startsWith(getModuleCache())) {
                + const cache = getModuleCache();
                + if (isMod && cache && cwd.startsWith(cache)) {
                return;
                }

                diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts
                index e713930..b8b5853 100644
                --- a/src/goInstallTools.ts
                +++ b/src/goInstallTools.ts
                @@ -56,7 +56,7 @@
                let allTools = getConfiguredTools(goVersion, getGoConfig(), getGoplsConfig());

                // exclude tools replaced by alternateTools.
                - const alternateTools: { [key: string]: string } = getGoConfig().get('alternateTools');
                + const alternateTools: { [key: string]: string } = getGoConfig().get('alternateTools') ?? {};
                allTools = allTools.filter((tool) => {
                return !alternateTools[tool.name];
                });
                @@ -154,7 +154,7 @@
                installingMsg += `the configured GOBIN: ${envForTools['GOBIN']}`;
                } else {
                const p = toolsGopath
                - .split(path.delimiter)
                + ?.split(path.delimiter)
                .map((e) => path.join(e, 'bin'))
                .join(path.delimiter);
                installingMsg += `${p}`;
                @@ -164,7 +164,7 @@
                // This ensures that users get the latest tagged version, rather than master,
                // which may be unstable.
                let modulesOff = false;
                - if (goVersion.lt('1.11')) {
                + if (goVersion?.lt('1.11')) {
                modulesOff = true;
                } else {
                installingMsg += ' in module mode.';
                @@ -225,7 +225,7 @@
                }

                // installTool installs the specified tool.
                -export async function installTool(tool: ToolAtVersion): Promise<string> {
                +export async function installTool(tool: ToolAtVersion): Promise<string | undefined> {
                const goVersion = await getGoForInstall(await getGoVersion());
                const envForTools = toolInstallationEnvironment();

                @@ -237,7 +237,7 @@
                goVersion: GoVersion, // go version to be used for installation.
                envForTools: NodeJS.Dict<string>,
                modulesOn: boolean
                -): Promise<string> {
                +): Promise<string | undefined> {
                // Some tools may have to be closed before we reinstall them.
                if (tool.close) {
                const reason = await tool.close(envForTools);
                @@ -253,7 +253,7 @@
                if (!modulesOn) {
                importPath = getImportPath(tool, goVersion);
                } else {
                - let version: semver.SemVer | string | undefined = tool.version;
                + let version: semver.SemVer | string | undefined | null = tool.version;
                if (!version) {
                if (tool.usePrereleaseInPreviewMode && extensionInfo.isPreview) {
                version = await latestToolVersion(tool, true);
                @@ -265,7 +265,7 @@
                }

                try {
                - if (!modulesOn || goVersion.lt('1.16') || hasModSuffix(tool)) {
                + if (!modulesOn || goVersion?.lt('1.16') || hasModSuffix(tool)) {
                await installToolWithGoGet(tool, goVersion, env, modulesOn, importPath);
                } else {
                await installToolWithGoInstall(goVersion, env, importPath);
                @@ -282,7 +282,7 @@
                async function installToolWithGoInstall(goVersion: GoVersion, env: NodeJS.Dict<string>, importPath: string) {
                // Unlike installToolWithGoGet, `go install` in module mode
                // can run in the current directory safely. So, use the user-specified go tool path.
                - const goBinary = goVersion.binaryPath || getBinPath('go');
                + const goBinary = goVersion?.binaryPath || getBinPath('go');
                const opts = {
                env,
                cwd: getWorkspaceFolderPath()
                @@ -306,7 +306,11 @@
                // (which can be a wrapper script that switches 'go').
                const goBinary = getCurrentGoRoot()
                ? path.join(getCurrentGoRoot(), 'bin', correctBinname('go'))
                - : goVersion.binaryPath;
                + : goVersion?.binaryPath;
                + if (!goBinary) {
                + vscode.window.showErrorMessage('Go binary not found.');
                + return;
                + }

                // Build the arguments list for the tool installation.
                const args = ['get', '-x'];
                @@ -332,6 +336,7 @@
                env,
                cwd: toolsTmpDir
                };
                +
                try {
                const execFile = util.promisify(cp.execFile);
                logVerbose(`$ ${goBinary} ${args.join(' ')} (cwd: ${opts.cwd})`);
                @@ -633,16 +638,16 @@

                function getMissingTools(goVersion: GoVersion): Promise<Tool[]> {
                const keys = getConfiguredTools(goVersion, getGoConfig(), getGoplsConfig());
                - return Promise.all<Tool>(
                + return Promise.all(
                keys.map(
                (tool) =>
                - new Promise<Tool>((resolve, reject) => {
                + new Promise<Tool | null>((resolve, reject) => {
                const toolPath = getBinPath(tool.name);
                resolve(path.isAbsolute(toolPath) ? null : tool);
                })
                )
                ).then((res) => {
                - return res.filter((x) => x != null);
                + return res.filter((x): x is Tool => x != null);
                });
                }

                @@ -741,7 +746,7 @@
                ...
                */
                const lines = stdout.split('\n', 3);
                - const goVersion = lines[0] && lines[0].match(/\s+(go\d+.\d+\S*)/)[1];
                + const goVersion = lines[0] && lines[0].match(/\s+(go\d+.\d+\S*)/)?.[1];
                const moduleVersion = lines[2].split(/\s+/)[3];
                return { goVersion, moduleVersion };
                } catch (e) {
                diff --git a/src/goLint.ts b/src/goLint.ts
                index 269763c..db1171c 100644
                --- a/src/goLint.ts
                +++ b/src/goLint.ts
                @@ -29,7 +29,7 @@
                }
                }

                - const documentUri = editor ? editor.document.uri : null;
                + const documentUri = editor ? editor.document.uri : undefined;
                const goConfig = getGoConfig(documentUri);
                const goplsConfig = getGoplsConfig(documentUri);

                @@ -39,7 +39,7 @@

                goLint(documentUri, goConfig, goplsConfig, scope)
                .then((warnings) => {
                - handleDiagnosticErrors(editor ? editor.document : null, warnings, lintDiagnosticCollection);
                + handleDiagnosticErrors(editor ? editor.document : undefined, warnings, lintDiagnosticCollection);
                diagnosticsStatusBarItem.hide();
                })
                .catch((err) => {
                @@ -56,7 +56,7 @@
                * @param scope Scope in which to run the linter.
                */
                export function goLint(
                - fileUri: vscode.Uri,
                + fileUri: vscode.Uri | undefined,
                goConfig: vscode.WorkspaceConfiguration,
                goplsConfig: vscode.WorkspaceConfiguration,
                scope?: string
                @@ -78,7 +78,7 @@

                const currentWorkspace = getWorkspaceFolderPath(fileUri);

                - const cwd = scope === 'workspace' && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);
                + const cwd = scope === 'workspace' && currentWorkspace ? currentWorkspace : path.dirname(fileUri?.fsPath ?? '');

                if (!path.isAbsolute(cwd)) {
                return Promise.resolve([]);
                @@ -128,8 +128,8 @@
                args.push('./...');
                outputChannel.appendLine(`Starting linting the current workspace at ${currentWorkspace}`);
                } else if (scope === 'file') {
                - args.push(fileUri.fsPath);
                - outputChannel.appendLine(`Starting linting the current file at ${fileUri.fsPath}`);
                + args.push(fileUri?.fsPath ?? '');
                + outputChannel.appendLine(`Starting linting the current file at ${fileUri?.fsPath}`);
                } else {
                outputChannel.appendLine(`Starting linting the current package at ${cwd}`);
                }
                diff --git a/src/goMain.ts b/src/goMain.ts
                index a8b44fb..22f06ec 100644
                --- a/src/goMain.ts
                +++ b/src/goMain.ts
                @@ -123,7 +123,7 @@
                return;
                };

                -export async function activate(ctx: vscode.ExtensionContext): Promise<ExtensionAPI> {
                +export async function activate(ctx: vscode.ExtensionContext): Promise<ExtensionAPI | undefined> {
                if (process.env['VSCODE_GO_IN_TEST'] === '1') {
                // Make sure this does not run when running in test.
                return;
                @@ -205,15 +205,11 @@
                // TODO: let configureLanguageServer to return its status.
                await configureLanguageServer(ctx);

                - if (
                - !languageServerIsRunning &&
                - vscode.window.activeTextEditor &&
                - vscode.window.activeTextEditor.document.languageId === 'go' &&
                - isGoPathSet()
                - ) {
                + const activeDoc = vscode.window.activeTextEditor?.document;
                + if (!languageServerIsRunning && activeDoc?.languageId === 'go' && isGoPathSet()) {
                // Check mod status so that cache is updated and then run build/lint/vet
                - isModSupported(vscode.window.activeTextEditor.document.uri).then(() => {
                - runBuilds(vscode.window.activeTextEditor.document, getGoConfig());
                + isModSupported(activeDoc.uri).then(() => {
                + runBuilds(activeDoc, getGoConfig());
                });
                }

                @@ -305,7 +301,9 @@

                ctx.subscriptions.push(
                vscode.commands.registerCommand('go.fill.struct', () => {
                - runFillStruct(vscode.window.activeTextEditor);
                + if (vscode.window.activeTextEditor) {
                + runFillStruct(vscode.window.activeTextEditor);
                + }
                })
                );

                @@ -697,7 +695,7 @@
                }
                applyCodeCoverageToAllEditors(
                coverProfilePath,
                - getWorkspaceFolderPath(vscode.window.activeTextEditor.document.uri)
                + getWorkspaceFolderPath(vscode.window.activeTextEditor?.document.uri)
                );
                });
                })
                @@ -899,7 +897,7 @@
                return;
                })
                );
                - return oldTools.filter((tool) => !!tool);
                + return oldTools.filter((tool): tool is Tool => !!tool);
                }

                async function suggestUpdates(ctx: vscode.ExtensionContext) {
                @@ -1019,7 +1017,7 @@
                outputChannel.appendLine(info);
                });

                - let folders = vscode.workspace.workspaceFolders?.map((folder) => {
                + let folders = vscode.workspace.workspaceFolders?.map<{ name: string; path?: string }>((folder) => {
                return { name: folder.name, path: folder.uri.fsPath };
                });
                if (!folders) {
                @@ -1059,7 +1057,7 @@
                if (goroot === currentGOROOT) {
                return;
                }
                - if (!(await dirExists(goroot))) {
                + if (!(await dirExists(goroot ?? ''))) {
                vscode.window.showWarningMessage(`go.goroot setting is ignored. ${goroot} is not a valid GOROOT directory.`);
                return;
                }
                diff --git a/src/goMode.ts b/src/goMode.ts
                index 6ff429e..0e7629f 100644
                --- a/src/goMode.ts
                +++ b/src/goMode.ts
                @@ -7,9 +7,14 @@

                import vscode = require('vscode');

                -export const GO_MODE: vscode.DocumentFilter = { language: 'go', scheme: 'file' };
                -export const GO_MOD_MODE: vscode.DocumentFilter = { language: 'go.mod', scheme: 'file' };
                -export const GO_SUM_MODE: vscode.DocumentFilter = { language: 'go.sum', scheme: 'file' };
                +interface Filter extends vscode.DocumentFilter {
                + language: string;
                + scheme: string;
                +}
                +
                +export const GO_MODE: Filter = { language: 'go', scheme: 'file' };
                +export const GO_MOD_MODE: Filter = { language: 'go.mod', scheme: 'file' };
                +export const GO_SUM_MODE: Filter = { language: 'go.sum', scheme: 'file' };

                export function isGoFile(document: vscode.TextDocument): boolean {
                if (
                diff --git a/src/goModifytags.ts b/src/goModifytags.ts
                index 8378c72..9ea6ea6 100644
                --- a/src/goModifytags.ts
                +++ b/src/goModifytags.ts
                @@ -89,11 +89,11 @@
                const editor = vscode.window.activeTextEditor;
                if (!editor) {
                vscode.window.showInformationMessage('No editor is active.');
                - return;
                + return [];
                }
                if (!editor.document.fileName.endsWith('.go')) {
                vscode.window.showInformationMessage('Current file is not a Go file.');
                - return;
                + return [];
                }
                const args = ['-modified', '-file', editor.document.fileName, '-format', 'json'];
                if (
                @@ -113,7 +113,7 @@
                return args;
                }

                -function getTagsAndOptions(config: GoTagsConfig, commandArgs: GoTagsConfig): Thenable<string[]> {
                +function getTagsAndOptions(config: GoTagsConfig, commandArgs: GoTagsConfig): Thenable<(string | undefined)[]> {
                const tags = commandArgs && commandArgs.hasOwnProperty('tags') ? commandArgs['tags'] : config['tags'];
                const options = commandArgs && commandArgs.hasOwnProperty('options') ? commandArgs['options'] : config['options'];
                const promptForTags =
                @@ -163,6 +163,9 @@
                function runGomodifytags(args: string[]) {
                const gomodifytags = getBinPath('gomodifytags');
                const editor = vscode.window.activeTextEditor;
                + if (!editor) {
                + return;
                + }
                const input = getFileArchive(editor.document);
                const p = cp.execFile(gomodifytags, args, { env: toolExecutionEnvironment() }, (err, stdout, stderr) => {
                if (err && (<any>err).code === 'ENOENT') {
                @@ -181,11 +184,11 @@
                return;
                }
                const output = <GomodifytagsOutput>JSON.parse(stdout);
                - vscode.window.activeTextEditor.edit((editBuilder) => {
                + editor.edit((editBuilder) => {
                editBuilder.replace(new vscode.Range(output.start - 1, 0, output.end, 0), output.lines.join('\n') + '\n');
                });
                });
                if (p.pid) {
                - p.stdin.end(input);
                + p.stdin?.end(input);
                }
                }
                diff --git a/src/goModules.ts b/src/goModules.ts
                index dcb770e..34d230e 100644
                --- a/src/goModules.ts
                +++ b/src/goModules.ts
                @@ -18,7 +18,7 @@
                import { getFromGlobalState, updateGlobalState } from './stateUtils';
                import { getBinPath, getGoVersion, getModuleCache, getWorkspaceFolderPath } from './util';
                import { envPath, fixDriveCasingInWindows, getCurrentGoRoot } from './utils/pathUtils';
                -export let GO111MODULE: string;
                +export let GO111MODULE: string | undefined;

                export async function runGoEnv(uri?: vscode.Uri, envvars: string[] = []): Promise<any> {
                const goExecutable = getBinPath('go');
                @@ -38,28 +38,28 @@
                }
                return JSON.parse(stdout);
                } catch (e) {
                - vscode.window.showErrorMessage(`Failed to run "go env ${args}": ${e.message}`);
                + vscode.window.showErrorMessage(`Failed to run "go env ${args}": ${(e as Error).message}`);
                return {};
                }
                }

                -export function isModSupported(fileuri: vscode.Uri, isDir?: boolean): Promise<boolean> {
                +export function isModSupported(fileuri?: vscode.Uri, isDir?: boolean): Promise<boolean> {
                return getModFolderPath(fileuri, isDir).then((modPath) => !!modPath);
                }

                export const packagePathToGoModPathMap: { [key: string]: string } = {};

                -export async function getModFolderPath(fileuri: vscode.Uri, isDir?: boolean): Promise<string> {
                - const pkgUri = isDir ? fileuri : vscodeUri.Utils.dirname(fileuri);
                - const pkgPath = pkgUri.fsPath;
                - if (packagePathToGoModPathMap[pkgPath]) {
                +export async function getModFolderPath(fileuri?: vscode.Uri, isDir?: boolean): Promise<string | undefined> {
                + const pkgUri = isDir ? fileuri : fileuri && vscodeUri.Utils.dirname(fileuri);
                + const pkgPath = pkgUri?.fsPath ?? '';
                + if (pkgPath && packagePathToGoModPathMap[pkgPath]) {
                return packagePathToGoModPathMap[pkgPath];
                }

                // We never would be using the path under module cache for anything
                // So, dont bother finding where exactly is the go.mod file
                const moduleCache = getModuleCache();
                - if (fixDriveCasingInWindows(fileuri.fsPath).startsWith(moduleCache)) {
                + if (moduleCache && fixDriveCasingInWindows(fileuri?.fsPath ?? '').startsWith(moduleCache)) {
                return moduleCache;
                }
                const goVersion = await getGoVersion();
                @@ -74,7 +74,7 @@
                goModEnvResult = path.dirname(goModEnvResult);
                const goConfig = getGoConfig(fileuri);

                - if (goConfig['inferGopath'] === true && !fileuri.path.includes('/vendor/')) {
                + if (goConfig['inferGopath'] === true && !fileuri?.path.includes('/vendor/')) {
                goConfig.update('inferGopath', false, vscode.ConfigurationTarget.WorkspaceFolder);
                vscode.window.showInformationMessage(
                'The "inferGopath" setting is disabled for this workspace because Go modules are being used.'
                @@ -122,7 +122,7 @@
                if (goConfig.get('useLanguageServer') === false) {
                goConfig.update('useLanguageServer', true, vscode.ConfigurationTarget.Global);
                }
                - if (goConfig.inspect('useLanguageServer').workspaceFolderValue === false) {
                + if (goConfig.inspect('useLanguageServer')?.workspaceFolderValue === false) {
                goConfig.update('useLanguageServer', true, vscode.ConfigurationTarget.WorkspaceFolder);
                }
                break;
                @@ -149,7 +149,7 @@
                }

                const moduleCache = getModuleCache();
                - if (cwd.startsWith(moduleCache)) {
                + if (moduleCache && cwd.startsWith(moduleCache)) {
                let importPath = cwd.substr(moduleCache.length + 1);
                const matches = /@v\d+(\.\d+)?(\.\d+)?/.exec(importPath);
                if (matches) {
                @@ -165,7 +165,7 @@
                console.warn(
                `Failed to run "go list" to find current package as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath})`
                );
                - return;
                + return '';
                }
                return new Promise<string>((resolve) => {
                const childProcess = cp.spawn(goRuntimePath, ['list'], { cwd, env: toolExecutionEnvironment() });
                @@ -200,17 +200,21 @@
                placeHolder: 'example/project'
                });

                + if (!moduleName) {
                + return;
                + }
                +
                const goRuntimePath = getBinPath('go');
                const execFile = util.promisify(cp.execFile);
                try {
                const env = toolExecutionEnvironment();
                - const cwd = getWorkspaceFolderPath();
                + const cwd = getWorkspaceFolderPath() ?? '';
                outputChannel.appendLine(`Running "${goRuntimePath} mod init ${moduleName}"`);
                await execFile(goRuntimePath, ['mod', 'init', moduleName], { env, cwd });
                outputChannel.appendLine('Module successfully initialized. You are ready to Go :)');
                vscode.commands.executeCommand('vscode.open', vscode.Uri.file(path.join(cwd, 'go.mod')));
                } catch (e) {
                - outputChannel.appendLine(e);
                + outputChannel.appendLine((e as Error).message);
                outputChannel.show();
                vscode.window.showErrorMessage(
                `Error running "${goRuntimePath} mod init ${moduleName}": See Go output channel for details`
                diff --git a/src/goPackages.ts b/src/goPackages.ts
                index af221da..e02828a 100644
                --- a/src/goPackages.ts
                +++ b/src/goPackages.ts
                @@ -124,7 +124,7 @@
                goListPkgs(workDir).then((pkgMap) => {
                goListPkgsRunning.delete(workDir);
                goListPkgsSubscriptions.delete(workDir);
                - subs.forEach((cb) => cb(pkgMap));
                + subs?.forEach((cb) => cb(pkgMap));
                });
                }
                });
                @@ -265,7 +265,7 @@
                console.warn(
                `Failed to run "go list" to find packages as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot()}) PATH(${envPath})`
                );
                - return;
                + return Promise.resolve(new Map());
                }

                return new Promise<Map<string, string>>((resolve, reject) => {
                diff --git a/src/goPlayground.ts b/src/goPlayground.ts
                index 3d0ad08..dc16de4 100644
                --- a/src/goPlayground.ts
                +++ b/src/goPlayground.ts
                @@ -32,7 +32,8 @@

                const selection = editor.selection;
                const code = selection.isEmpty ? editor.document.getText() : editor.document.getText(selection);
                - goPlay(code, getGoConfig(editor.document.uri).get('playground')).then(
                + const config: vscode.WorkspaceConfiguration | undefined = getGoConfig(editor.document.uri).get('playground');
                + goPlay(code, config).then(
                (result) => {
                outputChannel.append(result);
                },
                @@ -44,8 +45,8 @@
                );
                };

                -export function goPlay(code: string, goConfig: vscode.WorkspaceConfiguration): Thenable<string> {
                - const cliArgs = Object.keys(goConfig).map((key) => `-${key}=${goConfig[key]}`);
                +export function goPlay(code: string, goConfig?: vscode.WorkspaceConfiguration): Thenable<string> {
                + const cliArgs = goConfig ? Object.keys(goConfig).map((key) => `-${key}=${goConfig[key]}`) : [];
                const binaryLocation = getBinPath(TOOL_CMD_NAME);

                return new Promise<string>((resolve, reject) => {
                @@ -64,7 +65,7 @@
                );
                });
                if (p.pid) {
                - p.stdin.end(code);
                + p.stdin?.end(code);
                }
                });
                }
                diff --git a/src/goStatus.ts b/src/goStatus.ts
                index 6925623..56360e5 100644
                --- a/src/goStatus.ts
                +++ b/src/goStatus.ts
                @@ -39,7 +39,7 @@
                export const languageServerIcon = '$(zap)';
                export const languageServerErrorIcon = '$(warning)';

                -export async function updateGoStatusBar(editor: vscode.TextEditor) {
                +export async function updateGoStatusBar(editor: vscode.TextEditor | undefined) {
                // Only update the module path if we are in a Go file.
                // This allows the user to open output windows without losing
                // the go.mod information in the status bar.
                @@ -105,11 +105,13 @@
                break;
                case "Open 'go.work'":
                case "Open 'go.mod'":
                - const openPath = vscode.Uri.file(item.description);
                - vscode.workspace.openTextDocument(openPath).then((doc) => {
                - vscode.window.showTextDocument(doc);
                - });
                - break;
                + if (item.description) {
                + const openPath = vscode.Uri.file(item.description);
                + vscode.workspace.openTextDocument(openPath).then((doc) => {
                + vscode.window.showTextDocument(doc);
                + });
                + break;
                + }
                }
                }
                });
                diff --git a/src/goSurvey.ts b/src/goSurvey.ts
                index eeecd79..b55c2d4 100644
                --- a/src/goSurvey.ts
                +++ b/src/goSurvey.ts
                @@ -80,7 +80,7 @@
                setTimeout(callback, ms);
                }

                -export function shouldPromptForSurvey(now: Date, cfg: GoplsSurveyConfig): GoplsSurveyConfig {
                +export function shouldPromptForSurvey(now: Date, cfg: GoplsSurveyConfig): GoplsSurveyConfig | undefined {
                // If the prompt value is not set, assume we haven't prompted the user
                // and should do so.
                if (cfg.prompt === undefined) {
                @@ -145,7 +145,7 @@
                return Math.floor(Math.random() * (high - low + 1)) + low;
                }

                -async function promptForGoplsSurvey(cfg: GoplsSurveyConfig, now: Date): Promise<GoplsSurveyConfig> {
                +async function promptForGoplsSurvey(cfg: GoplsSurveyConfig = {}, now: Date): Promise<GoplsSurveyConfig> {
                let selected = await vscode.window.showInformationMessage(
                `Looks like you are using the Go extension for VS Code.
                Could you help us improve this extension by filling out a 1-2 minute survey about your experience with it?`,
                diff --git a/src/goTest.ts b/src/goTest.ts
                index 09875ad..d13d1ef 100644
                --- a/src/goTest.ts
                +++ b/src/goTest.ts
                @@ -22,12 +22,12 @@

                // lastTestConfig holds a reference to the last executed TestConfig which allows
                // the last test to be easily re-executed.
                -let lastTestConfig: TestConfig;
                +let lastTestConfig: TestConfig | undefined;

                // lastDebugConfig holds a reference to the last executed DebugConfiguration which allows
                // the last test to be easily re-executed and debugged.
                -let lastDebugConfig: vscode.DebugConfiguration;
                -let lastDebugWorkspaceFolder: vscode.WorkspaceFolder;
                +let lastDebugConfig: vscode.DebugConfiguration | undefined;
                +let lastDebugWorkspaceFolder: vscode.WorkspaceFolder | undefined;

                export type TestAtCursorCmd = 'debug' | 'test' | 'benchmark';

                @@ -43,13 +43,13 @@
                }

                const getFunctions = cmd === 'benchmark' ? getBenchmarkFunctions : getTestFunctions;
                - const testFunctions = await getFunctions(editor.document, null);
                + const testFunctions = (await getFunctions(editor.document)) ?? [];
                // We use functionName if it was provided as argument
                // Otherwise find any test function containing the cursor.
                const testFunctionName =
                args && args.functionName
                ? args.functionName
                - : testFunctions.filter((func) => func.range.contains(editor.selection.start)).map((el) => el.name)[0];
                + : testFunctions?.filter((func) => func.range.contains(editor.selection.start)).map((el) => el.name)[0];
                if (!testFunctionName) {
                throw new NotFoundError('No test function found at cursor.');
                }
                @@ -154,7 +154,7 @@

                await editor.document.save();
                try {
                - const testFunctions = await getTestFunctions(editor.document, null);
                + const testFunctions = (await getTestFunctions(editor.document)) ?? [];
                // We use functionName if it was provided as argument
                // Otherwise find any test function containing the cursor.
                const currentTestFunctions = testFunctions.filter((func) => func.range.contains(editor.selection.start));
                @@ -170,8 +170,8 @@
                const simpleRunRegex = /t.Run\("([^"]+)",/;
                const runRegex = /t.Run\(/;
                let lineText: string;
                - let runMatch: RegExpMatchArray | null;
                - let simpleMatch: RegExpMatchArray | null;
                + let runMatch: RegExpMatchArray | null | undefined;
                + let simpleMatch: RegExpMatchArray | null | undefined;
                for (let i = editor.selection.start.line; i >= testFunction.range.start.line; i--) {
                lineText = editor.document.lineAt(i).text;
                simpleMatch = lineText.match(simpleRunRegex);
                @@ -200,7 +200,7 @@

                return await runTestAtCursor(editor, subTestName, testFunctions, goConfig, 'test', args);
                } catch (err) {
                - vscode.window.showInformationMessage('Unable to run subtest: ' + err.toString());
                + vscode.window.showInformationMessage('Unable to run subtest: ' + (err as any).toString());
                console.error(err);
                }
                }
                @@ -289,16 +289,16 @@
                * @param goConfig Configuration for the Go extension.
                */
                export function testWorkspace(goConfig: vscode.WorkspaceConfiguration, args: any) {
                - if (!vscode.workspace.workspaceFolders.length) {
                + if (!vscode.workspace.workspaceFolders?.length) {
                vscode.window.showInformationMessage('No workspace is open to run tests.');
                return;
                }
                - let workspaceUri = vscode.workspace.workspaceFolders[0].uri;
                + let workspaceUri: vscode.Uri | undefined = vscode.workspace.workspaceFolders[0].uri;
                if (
                vscode.window.activeTextEditor &&
                vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri)
                ) {
                - workspaceUri = vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri).uri;
                + workspaceUri = vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri)!.uri;
                }

                const testConfig: TestConfig = {
                @@ -332,11 +332,11 @@
                const editor = vscode.window.activeTextEditor;
                if (!editor) {
                vscode.window.showInformationMessage('No editor is active.');
                - return;
                + return false;
                }
                if (!editor.document.fileName.endsWith('_test.go')) {
                vscode.window.showInformationMessage('No tests found. Current file is not a test file.');
                - return;
                + return false;
                }

                const getFunctions = isBenchmark ? getBenchmarkFunctions : getTestFunctions;
                @@ -345,12 +345,12 @@
                return editor.document
                .save()
                .then(() => {
                - return getFunctions(editor.document, null).then((testFunctions) => {
                + return getFunctions(editor.document).then((testFunctions) => {
                const testConfig: TestConfig = {
                goConfig,
                dir: path.dirname(editor.document.fileName),
                flags: getTestFlags(goConfig, args),
                - functions: testFunctions.map((sym) => sym.name),
                + functions: testFunctions?.map((sym) => sym.name),
                isBenchmark,
                isMod,
                applyCodeCoverage: goConfig.get<boolean>('coverOnSingleTestFile')
                @@ -360,7 +360,7 @@
                return goTest(testConfig);
                });
                })
                - .then(null, (err) => {
                + .then(undefined, (err) => {
                console.error(err);
                return Promise.resolve(false);
                });
                diff --git a/src/goTools.ts b/src/goTools.ts
                index a4b2007..65d2fdc 100644
                --- a/src/goTools.ts
                +++ b/src/goTools.ts
                @@ -36,15 +36,15 @@
                // latestVersion and latestVersionTimestamp are hardcoded default values
                // for the last known version of the given tool. We also hardcode values
                // for the latest known pre-release of the tool for the Nightly extension.
                - latestVersion?: semver.SemVer;
                + latestVersion?: semver.SemVer | null;
                latestVersionTimestamp?: moment.Moment;
                - latestPrereleaseVersion?: semver.SemVer;
                + latestPrereleaseVersion?: semver.SemVer | null;
                latestPrereleaseVersionTimestamp?: moment.Moment;

                // minimumGoVersion and maximumGoVersion set the range for the versions of
                // Go with which this tool can be used.
                - minimumGoVersion?: semver.SemVer;
                - maximumGoVersion?: semver.SemVer;
                + minimumGoVersion?: semver.SemVer | null;
                + maximumGoVersion?: semver.SemVer | null;

                // 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
                @@ -67,7 +67,7 @@
                */
                export function getImportPath(tool: Tool, goVersion: GoVersion): string {
                // For older versions of Go, install the older version of gocode.
                - if (tool.name === 'gocode' && goVersion.lt('1.10')) {
                + if (tool.name === 'gocode' && goVersion?.lt('1.10')) {
                return 'github.com/nsf/gocode';
                }
                return tool.importPath;
                @@ -75,7 +75,7 @@

                export function getImportPathWithVersion(
                tool: Tool,
                - version: semver.SemVer | string | undefined,
                + version: semver.SemVer | string | undefined | null,
                goVersion: GoVersion
                ): string {
                const importPath = getImportPath(tool, goVersion);
                @@ -129,7 +129,7 @@
                // TODO(github.com/golang/vscode-go/issues/388): decide what to do when
                // the go version is no longer supported by gopls while the legacy tools are
                // no longer working (or we remove the legacy language feature providers completely).
                - const useLanguageServer = goConfig['useLanguageServer'] && goVersion.gt('1.11');
                + const useLanguageServer = goConfig['useLanguageServer'] && goVersion?.gt('1.11');

                const tools: Tool[] = [];
                function maybeAddTool(name: string) {
                @@ -166,7 +166,7 @@
                }

                // gocode-gomod needed in go 1.11 & higher
                - if (goVersion.gt('1.10')) {
                + if (goVersion?.gt('1.10')) {
                maybeAddTool('gocode-gomod');
                }

                diff --git a/src/goVet.ts b/src/goVet.ts
                index 09ec8b7..25436e6 100644
                --- a/src/goVet.ts
                +++ b/src/goVet.ts
                @@ -27,14 +27,14 @@
                vscode.window.showInformationMessage('No editor is active, cannot find current package to vet');
                return;
                }
                - if (editor.document.languageId !== 'go' && !vetWorkspace) {
                + if (editor?.document.languageId !== 'go' && !vetWorkspace) {
                vscode.window.showInformationMessage(
                'File in the active editor is not a Go file, cannot find current package to vet'
                );
                return;
                }

                - const documentUri = editor ? editor.document.uri : null;
                + const documentUri = editor?.document.uri;
                const goConfig = getGoConfig(documentUri);

                outputChannel.clear(); // Ensures stale output from vet on save is cleared
                @@ -43,7 +43,7 @@

                goVet(documentUri, goConfig, vetWorkspace)
                .then((warnings) => {
                - handleDiagnosticErrors(editor ? editor.document : null, warnings, vetDiagnosticCollection);
                + handleDiagnosticErrors(editor?.document, warnings, vetDiagnosticCollection);
                diagnosticsStatusBarItem.hide();
                })
                .catch((err) => {
                @@ -60,7 +60,7 @@
                * @param vetWorkspace If true vets code in all workspace.
                */
                export async function goVet(
                - fileUri: vscode.Uri,
                + fileUri: vscode.Uri | undefined,
                goConfig: vscode.WorkspaceConfiguration,
                vetWorkspace?: boolean
                ): Promise<ICheckResult[]> {
                @@ -75,7 +75,7 @@
                tokenSource = new vscode.CancellationTokenSource();

                const currentWorkspace = getWorkspaceFolderPath(fileUri);
                - const cwd = vetWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);
                + const cwd = vetWorkspace && currentWorkspace ? currentWorkspace : (fileUri && path.dirname(fileUri.fsPath)) ?? '';
                if (!path.isAbsolute(cwd)) {
                return Promise.resolve([]);
                }
                @@ -112,7 +112,7 @@
                outputChannel.appendLine(`Starting "go vet" under the folder ${cwd}`);

                running = true;
                - return runTool(vetArgs, cwd, 'warning', true, null, vetEnv, false, tokenSource.token).then((result) => {
                + return runTool(vetArgs, cwd, 'warning', true, '', vetEnv, false, tokenSource.token).then((result) => {
                if (closureEpoch === epoch) {
                running = false;
                }
                diff --git a/src/goVulncheck.ts b/src/goVulncheck.ts
                index 097ec47..756e1af 100644
                --- a/src/goVulncheck.ts
                +++ b/src/goVulncheck.ts
                @@ -60,15 +60,20 @@
                default:
                return;
                }
                + if (!dir) {
                + return;
                + }

                let result = '\nNo known vulnerabilities found.';
                try {
                const vuln = await vulncheck(dir, pattern);
                - if (vuln.Vuln) {
                + if (vuln?.Vuln) {
                result = vuln.Vuln.map(renderVuln).join('----------------------\n');
                }
                } catch (e) {
                - result = e;
                + if (e instanceof Error) {
                + result = e.message;
                + }
                vscode.window.showErrorMessage(`error running vulncheck: ${e}`);
                }

                @@ -81,7 +86,7 @@
                private async activeDir() {
                const folders = vscode.workspace.workspaceFolders;
                if (!folders || folders.length === 0) return;
                - let dir = '';
                + let dir: string | undefined = '';
                if (folders.length === 1) {
                dir = folders[0].uri.path;
                } else {

                To view, visit change 401620. To unsubscribe, or for help writing mail filters, visit settings.

                Gerrit-Project: vscode-go
                Gerrit-Branch: master
                Gerrit-Change-Id: I18d3ea64f3022ee1ca722ace8d03ec8bbd51fe26
                Gerrit-Change-Number: 401620
                Gerrit-PatchSet: 8
                Gerrit-Owner: Jamal Carvalho <ja...@golang.org>
                Gerrit-Reviewer: Benny Siegert <bsie...@gmail.com>
                Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
                Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
                Gerrit-Reviewer: kokoro <noreply...@google.com>
                Gerrit-MessageType: merged
                Reply all
                Reply to author
                Forward
                0 new messages