Skip to content

Commit

Permalink
[debug] fix eclipse-theia#5769: watch support
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov committed Feb 24, 2020
1 parent 5d42711 commit 8ebaf5f
Show file tree
Hide file tree
Showing 30 changed files with 647 additions and 49 deletions.
1 change: 1 addition & 0 deletions packages/core/src/browser/icons/add-inverse.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/core/src/browser/icons/add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion packages/core/src/browser/shell/tab-bar-toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ export class TabBarToolbar extends ReactWidget {
if (iconClass) {
classNames.push(iconClass);
}
const tooltip = item.tooltip || (command && command.label);
return <div key={item.id} className={`${TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM}${command && this.commandIsEnabled(command.id) ? ' enabled' : ''}`}
onMouseDown={this.onMouseDownEvent} onMouseUp={this.onMouseUpEvent} onMouseOut={this.onMouseUpEvent} >
<div id={item.id} className={classNames.join(' ')} onClick={this.executeCommand} title={item.tooltip}>{innerText}</div>
<div id={item.id} className={classNames.join(' ')} onClick={this.executeCommand} title={tooltip}>{innerText}</div>
</div>;
}

Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/browser/source-tree/source-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ export class SourceTree extends TreeImpl {
const updated = existing && <TreeElementNode>Object.assign(existing, { element, parent });
if (CompositeTreeElement.hasElements(element)) {
if (updated) {
if (!ExpandableTreeNode.is(updated)) {
Object.assign(updated, { expanded: false });
}
if (!CompositeTreeNode.is(updated)) {
Object.assign(updated, { children: [] });
}
return updated;
}
return {
Expand All @@ -65,6 +71,12 @@ export class SourceTree extends TreeImpl {
delete updated.children;
}
if (updated) {
if (ExpandableTreeNode.is(updated)) {
delete updated.expanded;
}
if (CompositeTreeNode.is(updated)) {
delete updated.children;
}
return updated;
}
return {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/browser/source-tree/tree-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// tslint:disable:no-any

import { ReactNode } from 'react';
import { injectable } from 'inversify';
import { injectable, unmanaged } from 'inversify';
import { Emitter, Event } from '../../common/event';
import { MaybePromise } from '../../common/types';
import { Disposable, DisposableCollection } from '../../common/disposable';
Expand Down Expand Up @@ -57,7 +57,7 @@ export abstract class TreeSource implements Disposable {
readonly id: string | undefined;
readonly placeholder: string | undefined;

constructor(options: TreeSourceOptions = {}) {
constructor(@unmanaged() options: TreeSourceOptions = {}) {
this.id = options.id;
this.placeholder = options.placeholder;
}
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/browser/style/icons.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,15 @@
height: var(--theia-icon-size);
background: var(--theia-icon-open-json) no-repeat;
}

.theia-collapse-all-icon {
background: var(--theia-icon-collapse-all) center center no-repeat;
}

.theia-remove-all-icon {
background: var(--theia-icon-remove-all) center center no-repeat;
}

.theia-add-icon {
background: var(--theia-icon-add) center center no-repeat;
}
2 changes: 2 additions & 0 deletions packages/core/src/browser/style/variables-bright.useable.css
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ is not optimized for dense, information rich UIs.
--theia-icon-close-all: url(../icons/close-all-bright.svg);
--theia-icon-collapse: url(../icons/collapse.svg);
--theia-icon-collapse-all: url(../icons/CollapseAll.svg);
--theia-icon-remove-all: url(../icons/remove-all.svg);
--theia-icon-add: url(../icons/add.svg);
--theia-icon-clear: url(../icons/clear-search-results.svg);
--theia-icon-replace: url(../icons/replace.svg);
--theia-icon-replace-all: url(../icons/replace-all.svg);
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/browser/style/variables-dark.useable.css
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ is not optimized for dense, information rich UIs.
--theia-icon-close-all: url(../icons/close-all-dark.svg);
--theia-icon-collapse: url(../icons/collapse.svg);
--theia-icon-collapse-all: url(../icons/CollapseAll_inverse.svg);
--theia-icon-remove-all: url(../icons/remove-all-inverse.svg);
--theia-icon-add: url(../icons/add-inverse.svg);
--theia-icon-clear: url(../icons/clear-search-results-dark.svg);
--theia-icon-replace: url(../icons/replace-inverse.svg);
--theia-icon-replace-all: url(../icons/replace-all-inverse.svg);
Expand Down
78 changes: 51 additions & 27 deletions packages/debug/src/browser/console/debug-console-items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,24 @@ import { ConsoleItem, CompositeConsoleItem } from '@theia/console/lib/browser/co
import { DebugSession } from '../debug-session';
import { Severity } from '@theia/core/lib/common/severity';

export type DebugSessionProvider = () => DebugSession | undefined;

export class ExpressionContainer implements CompositeConsoleItem {

private static readonly BASE_CHUNK_SIZE = 100;

protected readonly session: DebugSession | undefined;
protected readonly sessionProvider: DebugSessionProvider;
protected get session(): DebugSession | undefined {
return this.sessionProvider();
}

protected variablesReference: number;
protected namedVariables: number | undefined;
protected indexedVariables: number | undefined;
protected readonly startOfVariables: number;

constructor(options: ExpressionContainer.Options) {
this.session = options.session;
this.sessionProvider = options.session;
this.variablesReference = options.variablesReference || 0;
this.namedVariables = options.namedVariables;
this.indexedVariables = options.indexedVariables;
Expand Down Expand Up @@ -72,9 +78,10 @@ export class ExpressionContainer implements CompositeConsoleItem {
for (let i = 0; i < numberOfChunks; i++) {
const start = this.startOfVariables + i * chunkSize;
const count = Math.min(chunkSize, this.indexedVariables - i * chunkSize);
const { session, variablesReference } = this;
const { variablesReference } = this;
result.push(new DebugVirtualVariable({
session, variablesReference,
session: this.sessionProvider,
variablesReference,
namedVariables: 0,
indexedVariables: count,
startOfVariables: start,
Expand All @@ -98,7 +105,7 @@ export class ExpressionContainer implements CompositeConsoleItem {
const names = new Set<string>();
for (const variable of variables) {
if (!names.has(variable.name)) {
result.push(new DebugVariable(this.session, variable, this));
result.push(new DebugVariable(this.sessionProvider, variable, this));
names.add(variable.name);
}
}
Expand All @@ -114,7 +121,7 @@ export class ExpressionContainer implements CompositeConsoleItem {
}
export namespace ExpressionContainer {
export interface Options {
session: DebugSession | undefined,
session: DebugSessionProvider,
variablesReference?: number
namedVariables?: number
indexedVariables?: number
Expand All @@ -128,7 +135,7 @@ export class DebugVariable extends ExpressionContainer {
static stringRegex = /^(['"]).*\1$/;

constructor(
protected readonly session: DebugSession | undefined,
session: DebugSessionProvider,
protected readonly variable: DebugProtocol.Variable,
protected readonly parent: ExpressionContainer
) {
Expand Down Expand Up @@ -264,55 +271,72 @@ export class ExpressionItem extends ExpressionContainer {
get value(): string {
return this._value;
}
protected _type: string | undefined;
get type(): string | undefined {
return this._type;
}

protected _available = false;
get available(): boolean {
return this._available;
}

constructor(
protected readonly expression: string,
protected readonly session: DebugSession | undefined
protected _expression: string,
session: DebugSessionProvider
) {
super({ session });
}

get expression(): string {
return this._expression;
}

render(): React.ReactNode {
const valueClassNames: string[] = [];
if (!this._available) {
valueClassNames.push(ConsoleItem.errorClassName);
valueClassNames.push('theia-debug-console-unavailable');
}
return <div className={'theia-debug-console-expression'}>
<div>{this.expression}</div>
<div>{this._expression}</div>
<div className={valueClassNames.join(' ')}>{this._value}</div>
</div>;
}

async evaluate(context: string = 'repl'): Promise<void> {
if (this.session) {
const session = this.session;
if (session) {
try {
const { expression } = this;
const body = await this.session.evaluate(expression, context);
if (body) {
this._value = body.result;
this._available = true;
this.variablesReference = body.variablesReference;
this.namedVariables = body.namedVariables;
this.indexedVariables = body.indexedVariables;
this.elements = undefined;
this.severity = Severity.Log;
}
const body = await session.evaluate(this._expression, context);
this.setResult(body);
} catch (err) {
this._value = err.message;
this._available = false;
this.severity = Severity.Error;
this.setResult(undefined, err.message);
}
} else {
this._value = 'Please start a debug session to evaluate';
this.setResult(undefined, 'Please start a debug session to evaluate');
}
}

protected setResult(body?: DebugProtocol.EvaluateResponse['body'], error: string = ExpressionItem.notAvailable): void {
if (body) {
this._value = body.result;
this._type = body.type;
this._available = true;
this.variablesReference = body.variablesReference;
this.namedVariables = body.namedVariables;
this.indexedVariables = body.indexedVariables;
this.severity = Severity.Log;
} else {
this._value = error;
this._type = undefined;
this._available = false;
this.variablesReference = 0;
this.namedVariables = undefined;
this.indexedVariables = undefined;
this.severity = Severity.Error;
}
this.elements = undefined;
}

}
Expand All @@ -321,7 +345,7 @@ export class DebugScope extends ExpressionContainer {

constructor(
protected readonly raw: DebugProtocol.Scope,
protected readonly session: DebugSession
session: DebugSessionProvider
) {
super({
session,
Expand Down
4 changes: 2 additions & 2 deletions packages/debug/src/browser/console/debug-console-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class DebugConsoleSession extends ConsoleSession {
}

async execute(value: string): Promise<void> {
const expression = new ExpressionItem(value, this.manager.currentSession);
const expression = new ExpressionItem(value, () => this.manager.currentSession);
this.items.push(expression);
await expression.evaluate();
this.fireDidChange();
Expand Down Expand Up @@ -160,7 +160,7 @@ export class DebugConsoleSession extends ConsoleSession {
}
const severity = category === 'stderr' ? Severity.Error : event.body.category === 'console' ? Severity.Warning : Severity.Info;
if (variablesReference) {
const items = await new ExpressionContainer({ session, variablesReference }).getElements();
const items = await new ExpressionContainer({ session: () => session, variablesReference }).getElements();
this.items.push(...items);
} else if (typeof body.output === 'string') {
for (const line of body.output.split('\n')) {
Expand Down
Loading

0 comments on commit 8ebaf5f

Please sign in to comment.