From f2b3556935a3aa9d277481e622d3025c07d6ed17 Mon Sep 17 00:00:00 2001 From: Anatoliy Bazko Date: Tue, 5 Nov 2019 14:19:58 +0200 Subject: [PATCH] Filter debug console outputs by severity Signed-off-by: Anatoliy Bazko --- .../console/src/browser/ansi-console-item.tsx | 4 +- .../src/browser/console-content-widget.tsx | 11 ++- .../console/src/browser/console-session.ts | 23 ++++- packages/core/src/common/severity.ts | 96 +++++++++++++++++++ ...tion.ts => debug-console-contribution.tsx} | 45 +++++++-- .../browser/console/debug-console-items.tsx | 8 +- .../browser/console/debug-console-session.ts | 10 +- .../browser/task-problem-matcher-registry.ts | 3 +- .../src/common/problem-matcher-protocol.ts | 53 +--------- .../src/node/task-abstract-line-matcher.ts | 3 +- .../src/node/task-problem-collector.spec.ts | 3 +- 11 files changed, 182 insertions(+), 77 deletions(-) create mode 100644 packages/core/src/common/severity.ts rename packages/debug/src/browser/console/{debug-console-contribution.ts => debug-console-contribution.tsx} (74%) diff --git a/packages/console/src/browser/ansi-console-item.tsx b/packages/console/src/browser/ansi-console-item.tsx index b9940879d0c05..078323bf49145 100644 --- a/packages/console/src/browser/ansi-console-item.tsx +++ b/packages/console/src/browser/ansi-console-item.tsx @@ -15,9 +15,9 @@ ********************************************************************************/ import * as React from 'react'; -import { MessageType } from '@theia/core/lib/common'; import { ConsoleItem } from './console-session'; import { ansiToHtml } from 'anser'; +import { Severity } from '@theia/core/lib/common/severity'; export class AnsiConsoleItem implements ConsoleItem { @@ -25,7 +25,7 @@ export class AnsiConsoleItem implements ConsoleItem { constructor( public readonly content: string, - public readonly severity?: MessageType + public readonly severity?: Severity ) { this.htmlContent = ansiToHtml(this.content, { use_classes: true, diff --git a/packages/console/src/browser/console-content-widget.tsx b/packages/console/src/browser/console-content-widget.tsx index 32c8784d40307..414c66f145c74 100644 --- a/packages/console/src/browser/console-content-widget.tsx +++ b/packages/console/src/browser/console-content-widget.tsx @@ -16,11 +16,12 @@ import { Message } from '@phosphor/messaging'; import { interfaces, Container, injectable } from 'inversify'; -import { MenuPath, MessageType } from '@theia/core'; +import { MenuPath } from '@theia/core'; import { TreeProps } from '@theia/core/lib/browser/tree'; import { TreeSourceNode } from '@theia/core/lib/browser/source-tree'; import { SourceTreeWidget, TreeElementNode } from '@theia/core/lib/browser/source-tree'; import { ConsoleItem } from './console-session'; +import { Severity } from '@theia/core/lib/common/severity'; @injectable() export class ConsoleContentWidget extends SourceTreeWidget { @@ -73,16 +74,16 @@ export class ConsoleContentWidget extends SourceTreeWidget { return classNames; } protected toClassName(item: ConsoleItem): string | undefined { - if (item.severity === MessageType.Error) { + if (item.severity === Severity.Error) { return ConsoleItem.errorClassName; } - if (item.severity === MessageType.Warning) { + if (item.severity === Severity.Warning) { return ConsoleItem.warningClassName; } - if (item.severity === MessageType.Info) { + if (item.severity === Severity.Info) { return ConsoleItem.infoClassName; } - if (item.severity === MessageType.Log) { + if (item.severity === Severity.Log) { return ConsoleItem.logClassName; } return undefined; diff --git a/packages/console/src/browser/console-session.ts b/packages/console/src/browser/console-session.ts index ed4ef2a4fb42f..ec87166955b65 100644 --- a/packages/console/src/browser/console-session.ts +++ b/packages/console/src/browser/console-session.ts @@ -16,11 +16,12 @@ import { injectable } from 'inversify'; import { MaybePromise } from '@theia/core/lib/common/types'; -import { MessageType } from '@theia/core/lib/common/message-service-protocol'; import { TreeSource, TreeElement, CompositeTreeElement } from '@theia/core/lib/browser/source-tree'; +import { Emitter } from '@theia/core/lib/common/event'; +import { Severity } from '@theia/core/lib/common/severity'; export interface ConsoleItem extends TreeElement { - readonly severity?: MessageType + readonly severity?: Severity; } export namespace ConsoleItem { export const errorClassName = 'theia-console-error'; @@ -35,6 +36,24 @@ export interface CompositeConsoleItem extends ConsoleItem, CompositeTreeElement @injectable() export abstract class ConsoleSession extends TreeSource { + protected selectedSeverity?: Severity; + protected readonly selectionEmitter: Emitter = new Emitter(); + readonly onSelectionChange = this.selectionEmitter.event; + + get severity(): Severity | undefined { + return this.selectedSeverity; + } + + set severity(severity: Severity | undefined) { + if (severity === this.selectedSeverity) { + return; + } + + this.selectedSeverity = severity; + this.selectionEmitter.fire(undefined); + this.fireDidChange(); + } + abstract getElements(): MaybePromise>; abstract execute(value: string): MaybePromise; abstract clear(): MaybePromise; diff --git a/packages/core/src/common/severity.ts b/packages/core/src/common/severity.ts new file mode 100644 index 0000000000000..c93bd20ad35e2 --- /dev/null +++ b/packages/core/src/common/severity.ts @@ -0,0 +1,96 @@ +/******************************************************************************** + * Copyright (C) 2019 Ericsson and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { DiagnosticSeverity } from 'vscode-languageserver-types'; + +export enum Severity { + Ignore = 0, + Error = 1, + Warning = 2, + Info = 3, + Log = 4 +} + +export namespace Severity { + const error = 'Errors'; + const warning = 'Warnings'; + const info = 'Info'; + const log = 'Log'; + const ignore = 'All'; + + export function fromValue(value: string | undefined): Severity { + value = value && value.toLowerCase(); + + if (!value) { + return Severity.Ignore; + } + if (['error', 'errors'].indexOf(value) !== -1) { + return Severity.Error; + } + if (['warn', 'warning', 'warnings'].indexOf(value) !== -1) { + return Severity.Warning; + } + if (value === 'info') { + return Severity.Info; + } + if (value === 'log') { + return Severity.Log; + } + + return Severity.Ignore; + } + + export function toDiagnosticSeverity(value: Severity): DiagnosticSeverity { + switch (value) { + case Severity.Ignore: + return DiagnosticSeverity.Hint; + case Severity.Info: + return DiagnosticSeverity.Information; + case Severity.Log: + return DiagnosticSeverity.Information; + case Severity.Warning: + return DiagnosticSeverity.Warning; + case Severity.Error: + return DiagnosticSeverity.Error; + default: + return DiagnosticSeverity.Error; + } + } + + export function toString(severity: Severity | undefined): string { + switch (severity) { + case Severity.Error: + return error; + case Severity.Warning: + return warning; + case Severity.Info: + return info; + case Severity.Log: + return log; + default: + return ignore; + } + } + + export function toArray(): string[] { + return [ignore, error, warning, info, log]; + } +} diff --git a/packages/debug/src/browser/console/debug-console-contribution.ts b/packages/debug/src/browser/console/debug-console-contribution.tsx similarity index 74% rename from packages/debug/src/browser/console/debug-console-contribution.ts rename to packages/debug/src/browser/console/debug-console-contribution.tsx index 253a6cf4cae2c..ba9c1ba6da066 100644 --- a/packages/debug/src/browser/console/debug-console-contribution.ts +++ b/packages/debug/src/browser/console/debug-console-contribution.tsx @@ -14,13 +14,15 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { interfaces, injectable } from 'inversify'; -import { AbstractViewContribution, bindViewContribution, WidgetFactory, Widget } from '@theia/core/lib/browser'; -import { ContextKeyService, ContextKey } from '@theia/core/lib/browser/context-key-service'; -import { ConsoleWidget, ConsoleOptions } from '@theia/console/lib/browser/console-widget'; -import { DebugConsoleSession } from './debug-console-session'; -import { Command, CommandRegistry } from '@theia/core/lib/common/command'; +import { ConsoleOptions, ConsoleWidget } from '@theia/console/lib/browser/console-widget'; +import { AbstractViewContribution, bindViewContribution, Widget, WidgetFactory } from '@theia/core/lib/browser'; +import { ContextKey, ContextKeyService } from '@theia/core/lib/browser/context-key-service'; import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; +import { Command, CommandRegistry } from '@theia/core/lib/common/command'; +import { Severity } from '@theia/core/lib/common/severity'; +import { inject, injectable, interfaces } from 'inversify'; +import * as React from 'react'; +import { DebugConsoleSession } from './debug-console-session'; export type InDebugReplContextKey = ContextKey; export const InDebugReplContextKey = Symbol('inDebugReplContextKey'); @@ -38,6 +40,9 @@ export namespace DebugConsoleCommands { @injectable() export class DebugConsoleContribution extends AbstractViewContribution implements TabBarToolbarContribution { + @inject(DebugConsoleSession) + protected debugConsoleSession: DebugConsoleSession; + constructor() { super({ widgetId: DebugConsoleContribution.options.id, @@ -61,7 +66,14 @@ export class DebugConsoleContribution extends AbstractViewContribution { + toolbarRegistry.registerItem({ + id: 'debug-console-severity', + render: widget => this.renderSeveritySelector(widget), + isVisible: widget => this.withWidget(widget, () => true), + onDidChange: this.debugConsoleSession.onSelectionChange + }); + toolbarRegistry.registerItem({ id: DebugConsoleCommands.CLEAR.id, command: DebugConsoleCommands.CLEAR.id, @@ -114,6 +126,25 @@ export class DebugConsoleContribution extends AbstractViewContribution severityElements.push()); + const selectedValue = Severity.toString(this.debugConsoleSession.severity || Severity.Ignore); + + return ; + } + + protected changeSeverity = (event: React.ChangeEvent) => { + this.debugConsoleSession.severity = Severity.fromValue(event.target.value); + } + protected withWidget(widget: Widget | undefined = this.tryGetWidget(), fn: (widget: ConsoleWidget) => T): T | false { if (widget instanceof ConsoleWidget && widget.id === DebugConsoleContribution.options.id) { return fn(widget); diff --git a/packages/debug/src/browser/console/debug-console-items.tsx b/packages/debug/src/browser/console/debug-console-items.tsx index ee05afbe78285..cfaaf7047315e 100644 --- a/packages/debug/src/browser/console/debug-console-items.tsx +++ b/packages/debug/src/browser/console/debug-console-items.tsx @@ -16,10 +16,10 @@ import * as React from 'react'; import { DebugProtocol } from 'vscode-debugprotocol/lib/debugProtocol'; -import { MessageType } from '@theia/core/lib/common'; import { SingleTextInputDialog } from '@theia/core/lib/browser'; import { ConsoleItem, CompositeConsoleItem } from '@theia/console/lib/browser/console-session'; import { DebugSession } from '../debug-session'; +import { Severity } from '@theia/core/lib/common/severity'; export class ExpressionContainer implements CompositeConsoleItem { @@ -104,7 +104,7 @@ export class ExpressionContainer implements CompositeConsoleItem { } } catch (e) { result.push({ - severity: MessageType.Error, + severity: Severity.Error, visible: !!e.message, render: () => e.message }); @@ -256,6 +256,7 @@ export namespace VirtualVariableItem { export class ExpressionItem extends ExpressionContainer { + severity?: Severity; static notAvailable = 'not available'; protected _value = ExpressionItem.notAvailable; @@ -299,14 +300,17 @@ export class ExpressionItem extends ExpressionContainer { this.namedVariables = body.namedVariables; this.indexedVariables = body.indexedVariables; this.elements = undefined; + this.severity = Severity.Log; } } catch (err) { this._value = err.message; this._available = false; + this.severity = Severity.Error; } } else { this._value = 'Please start a debug session to evaluate'; this._available = false; + this.severity = Severity.Error; } } diff --git a/packages/debug/src/browser/console/debug-console-session.ts b/packages/debug/src/browser/console/debug-console-session.ts index d3975f677c0b8..7972c307baa55 100644 --- a/packages/debug/src/browser/console/debug-console-session.ts +++ b/packages/debug/src/browser/console/debug-console-session.ts @@ -17,7 +17,6 @@ import throttle = require('lodash.throttle'); import { injectable, inject, postConstruct } from 'inversify'; import { DebugProtocol } from 'vscode-debugprotocol/lib/debugProtocol'; -import { MessageType } from '@theia/core/lib/common'; import { ConsoleSession, ConsoleItem } from '@theia/console/lib/browser/console-session'; import { AnsiConsoleItem } from '@theia/console/lib/browser/ansi-console-item'; import { DebugSession } from '../debug-session'; @@ -25,6 +24,7 @@ import { DebugSessionManager } from '../debug-session-manager'; import { Languages, CompletionItem, CompletionItemKind, Position, Range, TextEdit, Workspace, TextDocument, CompletionParams } from '@theia/languages/lib/browser'; import URI from '@theia/core/lib/common/uri'; import { ExpressionContainer, ExpressionItem } from './debug-console-items'; +import { Severity } from '@theia/core/lib/common/severity'; @injectable() export class DebugConsoleSession extends ConsoleSession { @@ -83,7 +83,7 @@ export class DebugConsoleSession extends ConsoleSession { } getElements(): IterableIterator { - return this.items[Symbol.iterator](); + return this.items.filter(e => !this.severity || e.severity === this.severity)[Symbol.iterator](); } protected async completions({ textDocument: { uri }, position }: CompletionParams): Promise { @@ -142,12 +142,12 @@ export class DebugConsoleSession extends ConsoleSession { this.uncompletedItemContent = value; } - this.items.push(new AnsiConsoleItem(this.uncompletedItemContent, MessageType.Info)); + this.items.push(new AnsiConsoleItem(this.uncompletedItemContent, Severity.Info)); this.fireDidChange(); } appendLine(value: string): void { - this.items.push(new AnsiConsoleItem(value, MessageType.Info)); + this.items.push(new AnsiConsoleItem(value, Severity.Info)); this.fireDidChange(); } @@ -158,7 +158,7 @@ export class DebugConsoleSession extends ConsoleSession { console.debug(`telemetry/${event.body.output}`, event.body.data); return; } - const severity = category === 'stderr' ? MessageType.Error : event.body.category === 'console' ? MessageType.Warning : MessageType.Info; + const severity = category === 'stderr' ? Severity.Error : event.body.category === 'console' ? Severity.Warning : Severity.Info; if (variablesReference) { const items = await new ExpressionContainer({ session, variablesReference }).getElements(); this.items.push(...items); diff --git a/packages/task/src/browser/task-problem-matcher-registry.ts b/packages/task/src/browser/task-problem-matcher-registry.ts index a884afcde36e6..7cd84f582aed2 100644 --- a/packages/task/src/browser/task-problem-matcher-registry.ts +++ b/packages/task/src/browser/task-problem-matcher-registry.ts @@ -23,10 +23,11 @@ import { inject, injectable, postConstruct } from 'inversify'; import { Event, Emitter } from '@theia/core/lib/common'; import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable'; import { - ApplyToKind, FileLocationKind, NamedProblemMatcher, Severity, + ApplyToKind, FileLocationKind, NamedProblemMatcher, ProblemPattern, ProblemMatcher, ProblemMatcherContribution, WatchingMatcher } from '../common'; import { ProblemPatternRegistry } from './task-problem-pattern-registry'; +import { Severity } from '@theia/core/lib/common/severity'; @injectable() export class ProblemMatcherRegistry { diff --git a/packages/task/src/common/problem-matcher-protocol.ts b/packages/task/src/common/problem-matcher-protocol.ts index 85bc2de24fbc3..92d2ecc7dd236 100644 --- a/packages/task/src/common/problem-matcher-protocol.ts +++ b/packages/task/src/common/problem-matcher-protocol.ts @@ -21,7 +21,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver-types'; +import { Severity } from '@theia/core/lib/common/severity'; +import { Diagnostic } from 'vscode-languageserver-types'; import vscodeURI from 'vscode-uri/lib/umd'; import { ProblemPatternContribution, WatchingMatcherContribution } from './task-protocol'; @@ -66,56 +67,6 @@ export namespace FileLocationKind { } } -export enum Severity { - Ignore = 0, - Info = 1, - Warning = 2, - Error = 3 -} - -export namespace Severity { - - const _error = 'error'; - const _warning = 'warning'; - const _warn = 'warn'; - const _info = 'info'; - - // Parses 'error', 'warning', 'warn', 'info' in call casings and falls back to ignore. - export function fromValue(value: string | undefined): Severity { - if (!value) { - return Severity.Ignore; - } - - if (value.toLowerCase() === _error) { - return Severity.Error; - } - - if (value.toLowerCase() === _warning || value.toLowerCase() === _warn) { - return Severity.Warning; - } - - if (value.toLowerCase() === _info) { - return Severity.Info; - } - return Severity.Ignore; - } - - export function toDiagnosticSeverity(value: Severity): DiagnosticSeverity { - switch (value) { - case Severity.Ignore: - return DiagnosticSeverity.Hint; - case Severity.Info: - return DiagnosticSeverity.Information; - case Severity.Warning: - return DiagnosticSeverity.Warning; - case Severity.Error: - return DiagnosticSeverity.Error; - default: - return DiagnosticSeverity.Error; - } - } -} - export interface WatchingPattern { regexp: string; file?: number; diff --git a/packages/task/src/node/task-abstract-line-matcher.ts b/packages/task/src/node/task-abstract-line-matcher.ts index 3cacfe030ef6a..55dc9f744ce37 100644 --- a/packages/task/src/node/task-abstract-line-matcher.ts +++ b/packages/task/src/node/task-abstract-line-matcher.ts @@ -23,10 +23,11 @@ import { isWindows } from '@theia/core/lib/common/os'; import { Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver-types'; import { FileLocationKind, ProblemMatcher, ProblemPattern, - ProblemMatch, ProblemMatchData, ProblemLocationKind, Severity + ProblemMatch, ProblemMatchData, ProblemLocationKind } from '../common/problem-matcher-protocol'; import URI from '@theia/core/lib/common/uri'; import vscodeURI from 'vscode-uri/lib/umd'; +import { Severity } from '@theia/core/lib/common/severity'; const endOfLine: string = isWindows ? '\r\n' : '\n'; diff --git a/packages/task/src/node/task-problem-collector.spec.ts b/packages/task/src/node/task-problem-collector.spec.ts index dd75d2f7c2f20..2931e23f93302 100644 --- a/packages/task/src/node/task-problem-collector.spec.ts +++ b/packages/task/src/node/task-problem-collector.spec.ts @@ -17,7 +17,8 @@ import { expect } from 'chai'; import { DiagnosticSeverity } from 'vscode-languageserver-types'; import { ProblemCollector } from './task-problem-collector'; -import { ApplyToKind, FileLocationKind, ProblemLocationKind, ProblemMatch, ProblemMatchData, ProblemMatcher, Severity } from '../common/problem-matcher-protocol'; +import { ApplyToKind, FileLocationKind, ProblemLocationKind, ProblemMatch, ProblemMatchData, ProblemMatcher } from '../common/problem-matcher-protocol'; +import { Severity } from '@theia/core/lib/common/severity'; const startStopMatcher1: ProblemMatcher = { owner: 'test1',