src/goVulncheck: prevent concurrent command execution

And fixed
 - The line number from gopls is 0-based. Fix that before printing
   in the output channel.
 - The file name may be missing if the file is a generated file,
   and most likely the line number is bogus too.
 - Adjust nesting to handle deep call stacks.

For golang/vscode-go#2096

Change-Id: I37d067bcedfe5a5618388cb723a32d0b5c54d317
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/402194
Reviewed-by: Suzy Mueller <suzmue@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/src/goVulncheck.ts b/src/goVulncheck.ts
index 9f2569f..097ec47 100644
--- a/src/goVulncheck.ts
+++ b/src/goVulncheck.ts
@@ -25,7 +25,22 @@
 
 	constructor(private channel: vscode.OutputChannel) {}
 
+	private running = false;
+
 	async run() {
+		if (this.running) {
+			vscode.window.showWarningMessage('another vulncheck is in progress');
+			return;
+		}
+		try {
+			this.running = true;
+			await this.runInternal();
+		} finally {
+			this.running = false;
+		}
+	}
+
+	private async runInternal() {
 		const pick = await vscode.window.showQuickPick(['Current Package', 'Workspace']);
 		let dir, pattern: string;
 		const filename = vscode.window.activeTextEditor?.document?.fileName;
@@ -112,9 +127,12 @@
 const renderStack = (v: Vuln) => {
 	const content = [];
 	for (const stack of v.CallStacks ?? []) {
-		for (const [i, line] of stack.entries()) {
-			const pad = Array.from('\t\t'.repeat(i)).join('');
-			content.push(`${pad}${line.Name}\n${pad}\t${renderUri(line)}`);
+		for (const [, line] of stack.entries()) {
+			content.push(`\t${line.Name}`);
+			const loc = renderUri(line);
+			if (loc) {
+				content.push(`\t\t${loc}`);
+			}
 		}
 		content.push('');
 	}
@@ -122,12 +140,17 @@
 };
 
 const renderUri = (stack: CallStack) => {
+	if (!stack.URI) {
+		// generated file or dummy location may not have a file name.
+		return '';
+	}
 	const parsed = vscode.Uri.parse(stack.URI);
+	const line = stack.Pos.line + 1; // Position uses 0-based line number.
 	const folder = vscode.workspace.getWorkspaceFolder(parsed);
 	if (folder) {
-		return `${parsed.path}:${stack.Pos.line}:${stack.Pos.character}`;
+		return `${parsed.path}:${line}:${stack.Pos.character}`;
 	}
-	return `${stack.URI}#${stack.Pos.line}:${stack.Pos.character}`;
+	return `${stack.URI}#${line}:${stack.Pos.character}`;
 };
 
 interface VulncheckReponse {