Repository: microsoft/vscode (TypeScript)
Date: 2022-11-16 18:54:03+00:00
Task type: Bug Fix

Issue:
Terminal Run quick fixes are showing a grey lightbulb instead of a run icon
![image](https://user-images.githubusercontent.com/2193314/202262358-91bb8ced-fca1-494f-b2a5-daf0c3ff14ee.png)

Version: 1.74.0-insider (user setup)
Commit: 39ff7eb93b513976b85b69085414cab11f8ed4cc
Date: 2022-11-16T14:18:57.639Z
Electron: 19.1.3
Chromium: 102.0.5005.167
Node.js: 16.14.2
V8: 10.2.154.15-electron.0
OS: Windows_NT x64 10.0.22621
Sandboxed: Yes


Issue discussion:

Solution patch:
diff --git a/src/vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions.ts
--- a/src/vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions.ts
+++ b/src/vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions.ts
@@ -7,6 +7,7 @@ import { localize } from 'vs/nls';
 import { TerminalQuickFixMatchResult, ITerminalQuickFixOptions, ITerminalInstance, TerminalQuickFixAction } from 'vs/workbench/contrib/terminal/browser/terminal';
 import { ITerminalCommand } from 'vs/workbench/contrib/terminal/common/terminal';
 import { IExtensionTerminalQuickFix } from 'vs/platform/terminal/common/terminal';
+import { TerminalQuickFixType } from 'vs/workbench/contrib/terminal/browser/widgets/terminalQuickFixMenuItems';
 export const GitCommandLineRegex = /git/;
 export const GitPushCommandLineRegex = /git\s+push/;
 export const GitTwoDashesRegex = /error: did you mean `--(.+)` \(with two dashes\)\?/;
@@ -41,7 +42,7 @@ export function gitSimilar(): ITerminalQuickFixOptions {
 				if (fixedCommand) {
 					actions.push({
 						id: 'Git Similar',
-						type: 'command',
+						type: TerminalQuickFixType.Command,
 						command: command.command.replace(/git\s+[^\s]+/, `git ${fixedCommand}`),
 						addNewLine: true
 					});
@@ -70,7 +71,7 @@ export function gitTwoDashes(): ITerminalQuickFixOptions {
 				return;
 			}
 			return {
-				type: 'command',
+				type: TerminalQuickFixType.Command,
 				id: 'Git Two Dashes',
 				command: command.command.replace(` -${problemArg}`, ` --${problemArg}`),
 				addNewLine: true
@@ -97,7 +98,7 @@ export function freePort(terminalInstance?: Partial<ITerminalInstance>): ITermin
 			}
 			const label = localize("terminal.freePort", "Free port {0}", port);
 			return {
-				class: undefined,
+				class: TerminalQuickFixType.Port,
 				tooltip: label,
 				id: 'terminal.freePort',
 				label,
diff --git a/src/vs/workbench/contrib/terminal/browser/widgets/terminalQuickFixMenuItems.ts b/src/vs/workbench/contrib/terminal/browser/widgets/terminalQuickFixMenuItems.ts
--- a/src/vs/workbench/contrib/terminal/browser/widgets/terminalQuickFixMenuItems.ts
+++ b/src/vs/workbench/contrib/terminal/browser/widgets/terminalQuickFixMenuItems.ts
@@ -10,14 +10,22 @@ import { localize } from 'vs/nls';
 import { ActionListItemKind, IListMenuItem } from 'vs/platform/actionWidget/browser/actionList';
 import { IActionItem } from 'vs/platform/actionWidget/common/actionWidget';
 
+export const enum TerminalQuickFixType {
+	Command = 'command',
+	Opener = 'opener',
+	Port = 'port'
+}
+
 export class TerminalQuickFix implements IActionItem {
 	action: IAction;
+	type: string;
 	disabled?: boolean;
 	title?: string;
-	constructor(action: IAction, title?: string, disabled?: boolean) {
+	constructor(action: IAction, type: string, title?: string, disabled?: boolean) {
 		this.action = action;
 		this.disabled = disabled;
 		this.title = title;
+		this.type = type;
 	}
 }
 
@@ -28,7 +36,7 @@ export function toMenuItems(inputQuickFixes: readonly TerminalQuickFix[], showHe
 		kind: ActionListItemKind.Header,
 		group: {
 			kind: CodeActionKind.QuickFix,
-			title: localize('codeAction.widget.id.quickfix', 'Quick Fix...')
+			title: localize('codeAction.widget.id.quickfix', 'Quick Fix')
 		}
 	});
 	for (const quickFix of showHeaders ? inputQuickFixes : inputQuickFixes.filter(i => !!i.action)) {
@@ -50,13 +58,13 @@ export function toMenuItems(inputQuickFixes: readonly TerminalQuickFix[], showHe
 }
 
 function getQuickFixIcon(quickFix: TerminalQuickFix): { codicon: Codicon } {
-	switch (quickFix.action.id) {
-		case 'quickFix.opener':
+	switch (quickFix.type) {
+		case TerminalQuickFixType.Opener:
 			// TODO: if it's a file link, use the open file icon
 			return { codicon: Codicon.link };
-		case 'quickFix.command':
+		case TerminalQuickFixType.Command:
 			return { codicon: Codicon.run };
-		case 'quickFix.freePort':
+		case TerminalQuickFixType.Port:
 			return { codicon: Codicon.debugDisconnect };
 	}
 	return { codicon: Codicon.lightBulb };
diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts
--- a/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts
+++ b/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts
@@ -24,11 +24,9 @@ import { IExtensionTerminalQuickFix } from 'vs/platform/terminal/common/terminal
 import { URI } from 'vs/base/common/uri';
 import { gitCreatePr, gitPushSetUpstream, gitSimilar } from 'vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions';
 import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
-import { ICommandService } from 'vs/platform/commands/common/commands';
 import { IActionWidgetService } from 'vs/platform/actionWidget/browser/actionWidget';
 import { ActionSet } from 'vs/platform/actionWidget/common/actionWidget';
-import { TerminalQuickFix, toMenuItems } from 'vs/workbench/contrib/terminal/browser/widgets/terminalQuickFixMenuItems';
-import { previewSelectedActionCommand } from 'vs/platform/actionWidget/browser/actionList';
+import { TerminalQuickFix, TerminalQuickFixType, toMenuItems } from 'vs/workbench/contrib/terminal/browser/widgets/terminalQuickFixMenuItems';
 
 const quickFixTelemetryTitle = 'terminal/quick-fix';
 type QuickFixResultTelemetryEvent = {
@@ -80,7 +78,6 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
 		@IOpenerService private readonly _openerService: IOpenerService,
 		@ITelemetryService private readonly _telemetryService: ITelemetryService,
 		@ILogService private readonly _logService: ILogService,
-		@ICommandService private readonly _commandService: ICommandService,
 		@IActionWidgetService private readonly _actionWidgetService: IActionWidgetService
 	) {
 		super();
@@ -233,7 +230,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
 				};
 				// TODO: What's documentation do? Need a vscode command?
 				const documentation = fixes.map(f => { return { id: f.id, title: f.label, tooltip: f.tooltip }; });
-				const actions = fixes.map(f => new TerminalQuickFix(f, f.label));
+				const actions = fixes.map(f => new TerminalQuickFix(f, f.class || TerminalQuickFixType.Command, f.label));
 				const actionSet = {
 					// TODO: Documentation and actions are separate?
 					documentation,
@@ -248,13 +245,9 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon,
 					return;
 				}
 				const delegate = {
-					onSelect: async (fix: TerminalQuickFix, preview?: boolean) => {
-						if (preview) {
-							this._commandService.executeCommand(previewSelectedActionCommand);
-						} else {
-							fix.action?.run();
-							this._actionWidgetService.hide();
-						}
+					onSelect: async (fix: TerminalQuickFix) => {
+						fix.action?.run();
+						this._actionWidgetService.hide();
 					},
 					onHide: () => {
 						this._terminal?.focus();
@@ -303,12 +296,12 @@ export function getQuickFixesForCommand(
 					let action: IAction | undefined;
 					if ('type' in quickFix) {
 						switch (quickFix.type) {
-							case 'command': {
+							case TerminalQuickFixType.Command: {
 								const label = localize('quickFix.command', 'Run: {0}', quickFix.command);
 								action = {
 									id: quickFix.id,
 									label,
-									class: undefined,
+									class: quickFix.type,
 									enabled: true,
 									run: () => {
 										onDidRequestRerunCommand?.fire({
@@ -322,12 +315,12 @@ export function getQuickFixesForCommand(
 								expectedCommands.push(quickFix.command);
 								break;
 							}
-							case 'opener': {
+							case TerminalQuickFixType.Opener: {
 								const label = localize('quickFix.opener', 'Open: {0}', quickFix.uri.toString());
 								action = {
-									id: `quickFix.opener`,
+									id: quickFix.id,
 									label,
-									class: undefined,
+									class: quickFix.type,
 									enabled: true,
 									run: () => {
 										openerService.open(quickFix.uri);
@@ -418,7 +411,7 @@ export function convertToQuickFixOptions(quickFix: IExtensionTerminalQuickFix):
 				}
 				link = link.replaceAll(varToResolve, value);
 			}
-			return link ? { type: 'opener', uri: URI.parse(link) } as ITerminalQuickFixOpenerAction : [];
+			return link ? { type: 'opener', uri: URI.parse(link), id: quickFix.id } as ITerminalQuickFixOpenerAction : [];
 		},
 		exitStatus: quickFix.exitStatus,
 		source: quickFix.extensionIdentifier


Test patch:
diff --git a/src/vs/workbench/contrib/terminal/test/browser/quickFixAddon.test.ts b/src/vs/workbench/contrib/terminal/test/browser/quickFixAddon.test.ts
--- a/src/vs/workbench/contrib/terminal/test/browser/quickFixAddon.test.ts
+++ b/src/vs/workbench/contrib/terminal/test/browser/quickFixAddon.test.ts
@@ -254,7 +254,7 @@ suite('QuickFixAddon', () => {
 			Branch 'test22' set up to track remote branch 'test22' from 'origin'. `;
 			const exitCode = 0;
 			const actions = [{
-				id: `quickFix.opener`,
+				id: 'Git Create Pr',
 				enabled: true,
 				label: 'Open: https://github.com/meganrogge/xterm.js/pull/new/test22',
 				tooltip: 'Open: https://github.com/meganrogge/xterm.js/pull/new/test22',