Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add generic marker sequence and markers/decorations for problems #152671

Merged
merged 31 commits into from
Jun 23, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2bb881a
add markers for problems
meganrogge Jun 20, 2022
9d01a4f
fix tests
meganrogge Jun 20, 2022
5812177
actually fix tests
meganrogge Jun 20, 2022
1e58802
Update src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts
meganrogge Jun 20, 2022
b9579bf
Update src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts
meganrogge Jun 20, 2022
451b646
put marker in better spot
meganrogge Jun 20, 2022
4797afb
get much closer
meganrogge Jun 20, 2022
fed7318
Merge branch 'main' into merogge/problem-marker
meganrogge Jun 20, 2022
69a565c
Merge branch 'main' into merogge/problem-marker
meganrogge Jun 20, 2022
686b40c
Merge branch 'main' into merogge/problem-marker
meganrogge Jun 22, 2022
5a3f512
register it as a command
meganrogge Jun 22, 2022
b1a4f1a
enable a custom hover
meganrogge Jun 22, 2022
b98d81d
invalidate command
meganrogge Jun 22, 2022
7887b6a
use number of matches
meganrogge Jun 22, 2022
04092be
tidy
meganrogge Jun 22, 2022
df5e8b4
Merge branch 'main' into merogge/problem-marker
meganrogge Jun 22, 2022
7c9a7b3
Merge branch 'main' into merogge/problem-marker
meganrogge Jun 22, 2022
60a7c31
fix test
meganrogge Jun 22, 2022
23d13aa
Update src/vs/platform/terminal/common/capabilities/capabilities.ts
meganrogge Jun 22, 2022
5040888
Merge branch 'main' into merogge/problem-marker
meganrogge Jun 22, 2022
b82fe91
Update src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts
meganrogge Jun 23, 2022
7a0271e
Update src/vs/workbench/contrib/terminal/browser/xterm/decorationAddo…
meganrogge Jun 23, 2022
be9e602
add e to file name
meganrogge Jun 23, 2022
3cb3fcb
cleanup
meganrogge Jun 23, 2022
5f80b23
big refactor
meganrogge Jun 23, 2022
66a8c5c
fix merge conflicts
meganrogge Jun 23, 2022
88ae78c
refactor
meganrogge Jun 23, 2022
29c5f3c
copy marker to capabilities file
meganrogge Jun 23, 2022
5316b57
handle marker in taskTerminalStatus
meganrogge Jun 23, 2022
4040a3b
Update src/vs/workbench/contrib/terminal/browser/terminal.ts
meganrogge Jun 23, 2022
c10717a
h
meganrogge Jun 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/vs/platform/terminal/common/capabilities/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { Event } from 'vs/base/common/event';
import { ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/terminalProcess';
import { IGenericCommandProperties, ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/terminalProcess';

/**
* Primarily driven by the shell integration feature, a terminal capability is the mechanism for
Expand Down Expand Up @@ -82,6 +82,15 @@ export interface ICwdDetectionCapability {
updateCwd(cwd: string): void;
}

export const enum CommandInvalidationReason {
Windows = 'windows',
NoProblemsReported = 'NoProblemsReported'
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}

export interface ICommandInvalidationRequest {
reason: CommandInvalidationReason;
}

export interface ICommandDetectionCapability {
readonly type: TerminalCapability.CommandDetection;
readonly commands: readonly ITerminalCommand[];
Expand All @@ -93,7 +102,7 @@ export interface ICommandDetectionCapability {
readonly onCommandStarted: Event<ITerminalCommand>;
readonly onCommandFinished: Event<ITerminalCommand>;
readonly onCommandInvalidated: Event<ITerminalCommand[]>;
readonly onCurrentCommandInvalidated: Event<void>;
readonly onCurrentCommandInvalidated: Event<ICommandInvalidationRequest>;
setCwd(value: string): void;
setIsWindowsPty(value: boolean): void;
setIsCommandStorageDisabled(): void;
Expand All @@ -108,8 +117,10 @@ export interface ICommandDetectionCapability {
handleRightPromptStart(): void;
handleRightPromptEnd(): void;
handleCommandStart(): void;
handleGenericCommand(properties: IGenericCommandProperties): void;
handleCommandExecuted(): void;
handleCommandFinished(exitCode: number | undefined): void;
handleCommandFinished(exitCode: number | undefined, genericProperties?: IGenericCommandProperties): void;
invalidateCurrentCommand(request: ICommandInvalidationRequest): void;
/**
* Set the command line explicitly.
*/
Expand Down Expand Up @@ -141,6 +152,7 @@ export interface ITerminalCommand {
commandStartLineContent?: string;
getOutput(): string | undefined;
hasOutput: boolean;
genericProperties?: IGenericCommandProperties;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { timeout } from 'vs/base/common/async';
import { debounce } from 'vs/base/common/decorators';
import { Emitter } from 'vs/base/common/event';
import { ILogService } from 'vs/platform/log/common/log';
import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand } from 'vs/platform/terminal/common/capabilities/capabilities';
import { ISerializedCommand, ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/terminalProcess';
import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand, ICommandInvalidationRequest, CommandInvalidationReason } from 'vs/platform/terminal/common/capabilities/capabilities';
import { IGenericCommandProperties, ISerializedCommand, ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/terminalProcess';
// Importing types is safe in any layer
// eslint-disable-next-line code-import-patterns
import type { IBuffer, IDisposable, IMarker, Terminal } from 'xterm-headless';
Expand Down Expand Up @@ -80,7 +80,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
readonly onCommandFinished = this._onCommandFinished.event;
private readonly _onCommandInvalidated = new Emitter<ITerminalCommand[]>();
readonly onCommandInvalidated = this._onCommandInvalidated.event;
private readonly _onCurrentCommandInvalidated = new Emitter<void>();
private readonly _onCurrentCommandInvalidated = new Emitter<ICommandInvalidationRequest>();
readonly onCurrentCommandInvalidated = this._onCurrentCommandInvalidated.event;

constructor(
Expand Down Expand Up @@ -120,7 +120,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
if (this._terminal.buffer.active.baseY + this._terminal.buffer.active.cursorY < this._currentCommand.commandStartMarker.line) {
this._clearCommandsInViewport();
this._currentCommand.isInvalid = true;
this._onCurrentCommandInvalidated.fire();
this._onCurrentCommandInvalidated.fire({ reason: CommandInvalidationReason.Windows });
}
}
}
Expand All @@ -137,7 +137,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
if (command.command.trim().toLowerCase() === 'clear' || command.command.trim().toLowerCase() === 'cls') {
this._clearCommandsInViewport();
this._currentCommand.isInvalid = true;
this._onCurrentCommandInvalidated.fire();
this._onCurrentCommandInvalidated.fire({ reason: CommandInvalidationReason.Windows });
}
}
});
Expand Down Expand Up @@ -300,7 +300,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
this._logService.debug('CommandDetectionCapability#handleRightPromptEnd', this._currentCommand.commandRightPromptEndX);
}

handleCommandStart(): void {
handleCommandStart(genericProperties?: IGenericCommandProperties): void {
// Only update the column if the line has already been set
if (this._currentCommand.commandStartMarker?.line === this._terminal.buffer.active.cursorY) {
this._currentCommand.commandStartX = this._terminal.buffer.active.cursorX;
Expand All @@ -313,7 +313,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
}
this._currentCommand.commandStartX = this._terminal.buffer.active.cursorX;
this._currentCommand.commandStartMarker = this._terminal.registerMarker(0);
this._onCommandStarted.fire({ marker: this._currentCommand.commandStartMarker } as ITerminalCommand);
this._onCommandStarted.fire({ marker: this._currentCommand.commandStartMarker, genericProperties } as ITerminalCommand);
this._logService.debug('CommandDetectionCapability#handleCommandStart', this._currentCommand.commandStartX, this._currentCommand.commandStartMarker?.line);
}

Expand Down Expand Up @@ -348,6 +348,14 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
});
}

handleGenericCommand(properties: IGenericCommandProperties): void {
this.setIsCommandStorageDisabled();
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
this.handlePromptStart();
this.handleCommandStart(properties);
this.handleCommandExecuted();
this.handleCommandFinished(undefined, properties);
}

handleCommandExecuted(): void {
if (this._isWindowsPty) {
this._handleCommandExecutedWindows();
Expand Down Expand Up @@ -393,7 +401,12 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
this._logService.debug('CommandDetectionCapability#handleCommandExecuted', this._currentCommand.commandExecutedX, this._currentCommand.commandExecutedMarker?.line);
}

handleCommandFinished(exitCode: number | undefined): void {
invalidateCurrentCommand(request: ICommandInvalidationRequest): void {
this._currentCommand.isInvalid = true;
this._onCurrentCommandInvalidated.fire(request);
}
meganrogge marked this conversation as resolved.
Show resolved Hide resolved

handleCommandFinished(exitCode: number | undefined, genericProperties?: IGenericCommandProperties): void {
if (this._isWindowsPty) {
this._preHandleCommandFinishedWindows();
}
Expand Down Expand Up @@ -434,7 +447,8 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
exitCode: this._exitCode,
commandStartLineContent: this._currentCommand.commandStartLineContent,
hasOutput: !!(executedMarker && endMarker && executedMarker?.line < endMarker!.line),
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer)
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer),
genericProperties
};
this._commands.push(newCommand);
this._logService.debug('CommandDetectionCapability#onCommandFinished', newCommand);
Expand Down Expand Up @@ -554,7 +568,8 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
commandStartLineContent: e.commandStartLineContent,
exitCode: e.exitCode,
hasOutput: !!(executedMarker && endMarker && executedMarker.line < endMarker.line),
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer)
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer),
genericProperties: e.genericProperties?.hoverMessage ? { hoverMessage: e.genericProperties.hoverMessage } : undefined
};
this._commands.push(newCommand);
this._logService.debug('CommandDetectionCapability#onCommandFinished', newCommand);
Expand Down
6 changes: 6 additions & 0 deletions src/vs/platform/terminal/common/terminalProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ export interface ISerializedCommand {
exitCode: number | undefined;
commandStartLineContent: string | undefined;
timestamp: number;
genericProperties?: IGenericCommandProperties;
}

export interface IGenericCommandProperties {
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
hoverMessage: string;
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}

export interface ISerializedCommandDetectionCapability {
isWindowsPty: boolean;
commands: ISerializedCommand[];
Expand Down
30 changes: 30 additions & 0 deletions src/vs/platform/terminal/common/xterm/shellIntegrationAddon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import type { ITerminalAddon, Terminal } from 'xterm-headless';
import { ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/terminalProcess';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Emitter } from 'vs/base/common/event';

/**
* Shell integration is a feature that enhances the terminal's understanding of what's happening
Expand Down Expand Up @@ -116,6 +117,16 @@ const enum VSCodeOscPt {
Property = 'P'
}

/**
* ITerm sequences
*/
const enum ITermOscPt {
/**
* Based on ITerm's `OSC 1337 ; SetMark`, sets a mark on the scroll bar
*/
SetMark = 'SetMark'
}

/**
* The shell integration addon extends xterm by reading shell integration sequences and creating
* capabilities and passing along relevant sequences to the capabilities. This is meant to
Expand All @@ -126,6 +137,8 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
readonly capabilities = new TerminalCapabilityStore();
private _hasUpdatedTelemetry: boolean = false;
private _activationTimeout: any;
private readonly _onRequestCreateGenericMarker = new Emitter<void>();
readonly onRequestCreateGenericMarker = this._onRequestCreateGenericMarker.event;
meganrogge marked this conversation as resolved.
Show resolved Hide resolved

constructor(
private readonly _disableTelemetry: boolean | undefined,
Expand All @@ -140,6 +153,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
this._terminal = xterm;
this.capabilities.add(TerminalCapability.PartialCommandDetection, new PartialCommandDetectionCapability(this._terminal));
this._register(xterm.parser.registerOscHandler(ShellIntegrationOscPs.VSCode, data => this._handleVSCodeSequence(data)));
this._register(xterm.parser.registerOscHandler(ShellIntegrationOscPs.ITerm, data => this._doHandleITermSequence(data)));
this._ensureCapabilitiesOrAddFailureTelemetry();
}

Expand Down Expand Up @@ -249,6 +263,22 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
return false;
}

private _doHandleITermSequence(data: string): boolean {
if (!this._terminal) {
return false;
}

const [command, value] = data.split(';');
switch (command) {
case ITermOscPt.SetMark: {
this._createOrGetCommandDetection(this._terminal).handleGenericCommand({ hoverMessage: value || '' });
}
meganrogge marked this conversation as resolved.
Show resolved Hide resolved
}

// Unrecognized sequence
return false;
}

serialize(): ISerializedCommandDetectionCapability {
if (!this._terminal || !this.capabilities.has(TerminalCapability.CommandDetection)) {
return {
Expand Down
3 changes: 3 additions & 0 deletions src/vs/workbench/contrib/tasks/browser/taskTerminalStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/termina
import { ITerminalStatus } from 'vs/workbench/contrib/terminal/browser/terminalStatusList';
import { MarkerSeverity } from 'vs/platform/markers/common/markers';
import { spinningLoading } from 'vs/platform/theme/common/iconRegistry';
import { CommandInvalidationReason, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities';

interface ITerminalData {
terminal: ITerminalInstance;
Expand Down Expand Up @@ -53,6 +54,8 @@ export class TaskTerminalStatus extends Disposable {
addTerminal(task: Task, terminal: ITerminalInstance, problemMatcher: AbstractProblemCollector) {
const status: ITerminalStatus = { id: TASK_TERMINAL_STATUS_ID, severity: Severity.Info };
terminal.statusList.add(status);
problemMatcher.onDidFindMatch(() => terminal.addGenericMarker('First error'));
problemMatcher.onDidInvalidateMatch(() => terminal.capabilities.get(TerminalCapability.CommandDetection)?.invalidateCurrentCommand({ reason: CommandInvalidationReason.NoProblemsReported }));
this.terminalMap.set(task._id, { terminal, task, status, problemMatcher, taskRunEnded: false });
}

Expand Down
7 changes: 4 additions & 3 deletions src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings';
import { GroupKind } from 'vs/workbench/contrib/tasks/common/taskConfiguration';
import { Codicon } from 'vs/base/common/codicons';
import { VSCodeOscProperty, VSCodeOscPt, VSCodeSequence } from 'vs/workbench/contrib/terminal/browser/terminalEscapSequences';

const taskShellIntegrationStartSequence = '\x1b]633;A\x07' + '\x1b]633;P;Task=\x07' + '\x1b]633;B\x07';
const taskShellIntegrationOutputSequence = '\x1b]633;C\x07';
const taskShellIntegrationStartSequence = VSCodeSequence(VSCodeOscPt.PromptStart) + VSCodeSequence(VSCodeOscPt.Property, VSCodeOscProperty.Task) + VSCodeSequence(VSCodeOscPt.CommandStart);
const taskShellIntegrationOutputSequence = VSCodeSequence(VSCodeOscPt.CommandExecuted);

interface ITerminalData {
terminal: ITerminalInstance;
Expand Down Expand Up @@ -1713,6 +1714,6 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem {

function taskShellIntegrationWaitOnExitSequence(message: string): (exitCode: number) => string {
return (exitCode) => {
return `\x1b]633;D;${exitCode}\x07${message}`;
return `${VSCodeSequence(VSCodeOscPt.CommandFinished, exitCode.toString())}${message}`;
};
}
12 changes: 11 additions & 1 deletion src/vs/workbench/contrib/tasks/common/problemCollectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export abstract class AbstractProblemCollector implements IDisposable {

private matchers: INumberDictionary<ILineMatcher[]>;
private activeMatcher: ILineMatcher | null;
private _numberOfMatches: number;
protected _numberOfMatches: number;
private _maxMarkerSeverity?: MarkerSeverity;
private buffer: string[];
private bufferLength: number;
Expand All @@ -58,6 +58,12 @@ export abstract class AbstractProblemCollector implements IDisposable {

protected _onDidStateChange: Emitter<IProblemCollectorEvent>;

protected readonly _onDidFindMatch = new Emitter<void>();
readonly onDidFindMatch = this._onDidFindMatch.event;

protected readonly _onDidInvalidateMatch = new Emitter<void>();
readonly onDidInvalidateMatch = this._onDidInvalidateMatch.event;

constructor(public readonly problemMatchers: ProblemMatcher[], protected markerService: IMarkerService, protected modelService: IModelService, fileService?: IFileService) {
this.matchers = Object.create(null);
this.bufferLength = 1;
Expand Down Expand Up @@ -492,6 +498,7 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement
}
this._activeBackgroundMatchers.add(background.key);
result = true;
this._onDidFindMatch.fire();
this.lines = [];
this.lines.push(line);
this._onDidStateChange.fire(IProblemCollectorEvent.create(ProblemCollectorEventKind.BackgroundProcessingBegins));
Expand All @@ -515,6 +522,9 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement
for (const background of this.backgroundPatterns) {
const matches = background.end.regexp.exec(line);
if (matches) {
if (this._numberOfMatches === 0) {
this._onDidInvalidateMatch.fire();
}
if (this._activeBackgroundMatchers.has(background.key)) {
this._activeBackgroundMatchers.delete(background.key);
this.resetCurrentResource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ class TestTask extends CommonTask {
}

class TestProblemCollector implements Partial<AbstractProblemCollector> {

private readonly _onDidFindMatch = new Emitter<void>();
readonly onDidFindMatch = this._onDidFindMatch.event;
private readonly _onDidInvalidateMatch = new Emitter<void>();
readonly onDidInvalidateMatch = this._onDidInvalidateMatch.event;
}

suite('Task Terminal Status', () => {
Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,11 @@ export interface ITerminalInstance {
*/
showEnvironmentInfoHover(): void;

/**
* Adds a generic marker and decoration to the buffer
*/
addGenericMarker(hoverMessage?: string): void;

/**
* Dispose the terminal instance, removing it from the panel/service and freeing up resources.
*
Expand Down