From 46bc8cf3ceb60accf87d5b640e59bb4f00954dcd Mon Sep 17 00:00:00 2001 From: sebastianwitthus <48671930+sebastianwitthus@users.noreply.github.com> Date: Tue, 9 Apr 2019 15:13:03 +0200 Subject: [PATCH] Automatically show problems panel (#71387) Add a presentaion option for tasks to automatically show the problems panel. Fixes #44146 --- .../contrib/tasks/common/jsonSchema_v2.ts | 15 +++++- .../contrib/tasks/common/taskConfiguration.ts | 16 +++++-- .../workbench/contrib/tasks/common/tasks.ts | 47 +++++++++++++++++-- .../electron-browser/task.contribution.ts | 3 +- .../electron-browser/terminalTaskSystem.ts | 29 +++++++++--- .../electron-browser/configuration.test.ts | 2 +- 6 files changed, 95 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts b/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts index 4c93a6cab287b..75c271d9a428b 100644 --- a/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts +++ b/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts @@ -100,16 +100,27 @@ const presentation: IJSONSchema = { default: false, description: nls.localize('JsonSchema.tasks.presentation.focus', 'Controls whether the panel takes focus. Default is false. If set to true the panel is revealed as well.') }, + revealProblem: { + type: 'string', + enum: ['always', 'onProblem', 'never'], + enumDescriptions: [ + nls.localize('JsonSchema.tasks.presentation.revealProblem.always', 'Always reveals the problems panel when this task is executed.'), + nls.localize('JsonSchema.tasks.presentation.revealProblem.onProblem', 'Only reveals the problems panel if a problem is found.'), + nls.localize('JsonSchema.tasks.presentation.revealProblem.never', 'Never reveals the problems panel when this task is executed.'), + ], + default: 'never', + description: nls.localize('JsonSchema.tasks.presentation.revealProblem', 'Controls whether the problems panel is revealed when running this task or not. Takes precedence over option \"reveal\". Default is \"never\".') + }, reveal: { type: 'string', enum: ['always', 'silent', 'never'], enumDescriptions: [ nls.localize('JsonSchema.tasks.presentation.reveal.always', 'Always reveals the terminal when this task is executed.'), - nls.localize('JsonSchema.tasks.presentation.reveal.silent', 'Only reveals the terminal if the task exits with an error.'), + nls.localize('JsonSchema.tasks.presentation.reveal.silent', 'Only reveals the terminal if the task exits with an error or the problem matcher finds an error.'), nls.localize('JsonSchema.tasks.presentation.reveal.never', 'Never reveals the terminal when this task is executed.'), ], default: 'always', - description: nls.localize('JsonSchema.tasks.presentation.reveals', 'Controls whether the panel running the task is revealed or not. Default is \"always\".') + description: nls.localize('JsonSchema.tasks.presentation.reveals', 'Controls whether the panel running the task is revealed or not. May be overridden by option \"revealProblem\". Default is \"always\".') }, panel: { type: 'string', diff --git a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts index b5e53b5d38943..117219610011f 100644 --- a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts +++ b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts @@ -91,6 +91,12 @@ export interface PresentationOptionsConfig { */ reveal?: string; + /** + * Controls whether the problems panel is revealed when running this task or not. + * Defaults to `RevealKind.Never`. + */ + revealProblem?: string; + /** * Controls whether the executed command is printed to the output window or terminal as well. */ @@ -796,7 +802,7 @@ namespace CommandOptions { namespace CommandConfiguration { export namespace PresentationOptions { - const properties: MetaData[] = [{ property: 'echo' }, { property: 'reveal' }, { property: 'focus' }, { property: 'panel' }, { property: 'showReuseMessage' }, { property: 'clear' }, { property: 'group' }]; + const properties: MetaData[] = [{ property: 'echo' }, { property: 'reveal' }, { property: 'revealProblem' }, { property: 'focus' }, { property: 'panel' }, { property: 'showReuseMessage' }, { property: 'clear' }, { property: 'group' }]; interface PresentationOptionsShape extends LegacyCommandProperties { presentation?: PresentationOptionsConfig; @@ -805,6 +811,7 @@ namespace CommandConfiguration { export function from(this: void, config: PresentationOptionsShape, context: ParseContext): Tasks.PresentationOptions | undefined { let echo: boolean; let reveal: Tasks.RevealKind; + let revealProblem: Tasks.RevealProblemKind; let focus: boolean; let panel: Tasks.PanelKind; let showReuseMessage: boolean; @@ -827,6 +834,9 @@ namespace CommandConfiguration { if (Types.isString(presentation.reveal)) { reveal = Tasks.RevealKind.fromString(presentation.reveal); } + if (Types.isString(presentation.revealProblem)) { + revealProblem = Tasks.RevealProblemKind.fromString(presentation.revealProblem); + } if (Types.isBoolean(presentation.focus)) { focus = presentation.focus; } @@ -847,7 +857,7 @@ namespace CommandConfiguration { if (!hasProps) { return undefined; } - return { echo: echo!, reveal: reveal!, focus: focus!, panel: panel!, showReuseMessage: showReuseMessage!, clear: clear!, group }; + return { echo: echo!, reveal: reveal!, revealProblem: revealProblem!, focus: focus!, panel: panel!, showReuseMessage: showReuseMessage!, clear: clear!, group }; } export function assignProperties(target: Tasks.PresentationOptions, source: Tasks.PresentationOptions | undefined): Tasks.PresentationOptions | undefined { @@ -860,7 +870,7 @@ namespace CommandConfiguration { export function fillDefaults(value: Tasks.PresentationOptions, context: ParseContext): Tasks.PresentationOptions | undefined { let defaultEcho = context.engine === Tasks.ExecutionEngine.Terminal ? true : false; - return _fillDefaults(value, { echo: defaultEcho, reveal: Tasks.RevealKind.Always, focus: false, panel: Tasks.PanelKind.Shared, showReuseMessage: true, clear: false }, properties, context); + return _fillDefaults(value, { echo: defaultEcho, reveal: Tasks.RevealKind.Always, revealProblem: Tasks.RevealProblemKind.Never, focus: false, panel: Tasks.PanelKind.Shared, showReuseMessage: true, clear: false }, properties, context); } export function freeze(value: Tasks.PresentationOptions): Readonly | undefined { diff --git a/src/vs/workbench/contrib/tasks/common/tasks.ts b/src/vs/workbench/contrib/tasks/common/tasks.ts index 2ea5bc296bfce..c1f97913eb9ca 100644 --- a/src/vs/workbench/contrib/tasks/common/tasks.ts +++ b/src/vs/workbench/contrib/tasks/common/tasks.ts @@ -12,8 +12,8 @@ import { UriComponents } from 'vs/base/common/uri'; import { ProblemMatcher } from 'vs/workbench/contrib/tasks/common/problemMatcher'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; export const TASK_RUNNING_STATE = new RawContextKey('taskRunning', false); @@ -123,7 +123,9 @@ export enum RevealKind { /** * Only brings the terminal to front if a problem is detected executing the task - * (e.g. the task couldn't be started because). + * e.g. the task couldn't be started, + * the task ended with an exit code other than zero, + * or the problem matcher found an error. */ Silent = 2, @@ -148,6 +150,39 @@ export namespace RevealKind { } } +export enum RevealProblemKind { + /** + * Never reveals the problems panel when this task is executed. + */ + Never = 1, + + + /** + * Only reveals the problems panel if a problem is found. + */ + OnProblem = 2, + + /** + * Never reveals the problems panel when this task is executed. + */ + Always = 3 +} + +export namespace RevealProblemKind { + export function fromString(this: void, value: string): RevealProblemKind { + switch (value.toLowerCase()) { + case 'always': + return RevealProblemKind.Always; + case 'never': + return RevealProblemKind.Never; + case 'onproblem': + return RevealProblemKind.OnProblem; + default: + return RevealProblemKind.OnProblem; + } + } +} + export enum PanelKind { /** @@ -189,6 +224,12 @@ export interface PresentationOptions { */ reveal: RevealKind; + /** + * Controls whether the problems pane is revealed when running this task or not. + * Defaults to `RevealProblemKind.Never`. + */ + revealProblem: RevealProblemKind; + /** * Controls whether the command associated with the task is echoed * in the user interface. @@ -225,7 +266,7 @@ export interface PresentationOptions { export namespace PresentationOptions { export const defaults: PresentationOptions = { - echo: true, reveal: RevealKind.Always, focus: false, panel: PanelKind.Shared, showReuseMessage: true, clear: false + echo: true, reveal: RevealKind.Always, revealProblem: RevealProblemKind.Never, focus: false, panel: PanelKind.Shared, showReuseMessage: true, clear: false }; } diff --git a/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts b/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts index c8051ba87c0b5..28debe808c8ff 100644 --- a/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts +++ b/src/vs/workbench/contrib/tasks/electron-browser/task.contribution.ts @@ -467,6 +467,7 @@ class TaskService extends Disposable implements ITaskService { @IConfigurationService private readonly configurationService: IConfigurationService, @IMarkerService private readonly markerService: IMarkerService, @IOutputService private readonly outputService: IOutputService, + @IPanelService private readonly panelService: IPanelService, @IEditorService private readonly editorService: IEditorService, @IFileService private readonly fileService: IFileService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @@ -1353,7 +1354,7 @@ class TaskService extends Disposable implements ITaskService { } if (this.executionEngine === ExecutionEngine.Terminal) { this._taskSystem = new TerminalTaskSystem( - this.terminalService, this.outputService, this.markerService, + this.terminalService, this.outputService, this.panelService, this.markerService, this.modelService, this.configurationResolverService, this.telemetryService, this.contextService, this._environmentService, TaskService.OutputChannelId, diff --git a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts index cbb39c0189849..0b727f13ce566 100644 --- a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts @@ -22,6 +22,7 @@ import { IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/marke import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ProblemMatcher, ProblemMatcherRegistry /*, ProblemPattern, getResource */ } from 'vs/workbench/contrib/tasks/common/problemMatcher'; +import Constants from 'vs/workbench/contrib/markers/browser/constants'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -31,7 +32,7 @@ import { IOutputService } from 'vs/workbench/contrib/output/common/output'; import { StartStopProblemCollector, WatchingProblemCollector, ProblemCollectorEventKind } from 'vs/workbench/contrib/tasks/common/problemCollectors'; import { Task, CustomTask, ContributedTask, RevealKind, CommandOptions, ShellConfiguration, RuntimeType, PanelKind, - TaskEvent, TaskEventKind, ShellQuotingOptions, ShellQuoting, CommandString, CommandConfiguration, ExtensionTaskSource, TaskScope + TaskEvent, TaskEventKind, ShellQuotingOptions, ShellQuoting, CommandString, CommandConfiguration, ExtensionTaskSource, TaskScope, RevealProblemKind } from 'vs/workbench/contrib/tasks/common/tasks'; import { ITaskSystem, ITaskSummary, ITaskExecuteResult, TaskExecuteKind, TaskError, TaskErrors, ITaskResolver, @@ -42,6 +43,7 @@ import { URI } from 'vs/base/common/uri'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { Schemas } from 'vs/base/common/network'; import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; +import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; interface TerminalData { terminal: ITerminalInstance; @@ -162,6 +164,7 @@ export class TerminalTaskSystem implements ITaskSystem { constructor( private terminalService: ITerminalService, private outputService: IOutputService, + private panelService: IPanelService, private markerService: IMarkerService, private modelService: IModelService, private configurationResolverService: IConfigurationResolverService, private telemetryService: ITelemetryService, @@ -517,11 +520,16 @@ export class TerminalTaskSystem implements ITaskSystem { eventCounter--; this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.Inactive, task)); if (eventCounter === 0) { - let reveal = task.command.presentation!.reveal; - if ((reveal === RevealKind.Silent) && (watchingProblemMatcher.numberOfMatches > 0) && watchingProblemMatcher.maxMarkerSeverity && + if ((watchingProblemMatcher.numberOfMatches > 0) && watchingProblemMatcher.maxMarkerSeverity && (watchingProblemMatcher.maxMarkerSeverity >= MarkerSeverity.Error)) { - this.terminalService.setActiveInstance(terminal!); - this.terminalService.showPanel(false); + let reveal = task.command.presentation!.reveal; + let revealProblem = task.command.presentation!.revealProblem; + if (revealProblem === RevealProblemKind.OnProblem) { + this.panelService.openPanel(Constants.MARKERS_PANEL_ID, true); + } else if (reveal === RevealKind.Silent) { + this.terminalService.setActiveInstance(terminal!); + this.terminalService.showPanel(false); + } } } } @@ -645,7 +653,11 @@ export class TerminalTaskSystem implements ITaskSystem { } } let reveal = task.command.presentation!.reveal; - if (terminal && (reveal === RevealKind.Silent) && ((exitCode !== 0) || (startStopProblemMatcher.numberOfMatches > 0) && startStopProblemMatcher.maxMarkerSeverity && + let revealProblem = task.command.presentation!.revealProblem; + let revealProblemPanel = terminal && (revealProblem === RevealProblemKind.OnProblem) && (startStopProblemMatcher.numberOfMatches > 0); + if (revealProblemPanel) { + this.panelService.openPanel(Constants.MARKERS_PANEL_ID); + } else if (terminal && (reveal === RevealKind.Silent) && ((exitCode !== 0) || (startStopProblemMatcher.numberOfMatches > 0) && startStopProblemMatcher.maxMarkerSeverity && (startStopProblemMatcher.maxMarkerSeverity >= MarkerSeverity.Error))) { this.terminalService.setActiveInstance(terminal); this.terminalService.showPanel(false); @@ -676,7 +688,10 @@ export class TerminalTaskSystem implements ITaskSystem { if (!terminal) { return Promise.reject(new Error(`Failed to create terminal for task ${task._label}`)); } - if (task.command.presentation && (task.command.presentation.reveal === RevealKind.Always)) { + let showProblemPanel = task.command.presentation && (task.command.presentation.revealProblem === RevealProblemKind.Always); + if (showProblemPanel) { + this.panelService.openPanel(Constants.MARKERS_PANEL_ID); + } else if (task.command.presentation && (task.command.presentation.reveal === RevealKind.Always)) { this.terminalService.setActiveInstance(terminal); this.terminalService.showPanel(task.command.presentation.focus); } diff --git a/src/vs/workbench/contrib/tasks/test/electron-browser/configuration.test.ts b/src/vs/workbench/contrib/tasks/test/electron-browser/configuration.test.ts index de2442738e2ce..191adbb0ee489 100644 --- a/src/vs/workbench/contrib/tasks/test/electron-browser/configuration.test.ts +++ b/src/vs/workbench/contrib/tasks/test/electron-browser/configuration.test.ts @@ -83,7 +83,7 @@ class PresentationBuilder { public result: Tasks.PresentationOptions; constructor(public parent: CommandConfigurationBuilder) { - this.result = { echo: false, reveal: Tasks.RevealKind.Always, focus: false, panel: Tasks.PanelKind.Shared, showReuseMessage: true, clear: false }; + this.result = { echo: false, reveal: Tasks.RevealKind.Always, revealProblem: Tasks.RevealProblemKind.Never, focus: false, panel: Tasks.PanelKind.Shared, showReuseMessage: true, clear: false }; } public echo(value: boolean): PresentationBuilder {