@theia/debug 1.53.0-next.5 → 1.53.0-next.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -62
- package/lib/browser/debug-configuration-manager.js +6 -6
- package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
- package/lib/browser/debug-frontend-application-contribution.js.map +1 -1
- package/lib/common/inline-debug-adapter.d.ts +1 -0
- package/lib/common/inline-debug-adapter.d.ts.map +1 -1
- package/package.json +16 -16
- package/src/browser/breakpoint/breakpoint-manager.ts +369 -369
- package/src/browser/breakpoint/breakpoint-marker.ts +104 -104
- package/src/browser/console/debug-console-contribution.tsx +240 -240
- package/src/browser/console/debug-console-items.tsx +384 -384
- package/src/browser/console/debug-console-session.ts +205 -205
- package/src/browser/debug-call-stack-item-type-key.ts +20 -20
- package/src/browser/debug-configuration-manager.ts +591 -591
- package/src/browser/debug-configuration-model.ts +100 -100
- package/src/browser/debug-contribution.ts +43 -43
- package/src/browser/debug-frontend-application-contribution.ts +1551 -1551
- package/src/browser/debug-frontend-module.ts +133 -133
- package/src/browser/debug-package.spec.ts +20 -20
- package/src/browser/debug-preferences.ts +98 -98
- package/src/browser/debug-prefix-configuration.ts +195 -195
- package/src/browser/debug-resource.ts +59 -59
- package/src/browser/debug-schema-updater.ts +149 -149
- package/src/browser/debug-session-connection.ts +357 -357
- package/src/browser/debug-session-contribution.ts +157 -157
- package/src/browser/debug-session-manager.ts +683 -683
- package/src/browser/debug-session-options.ts +120 -120
- package/src/browser/debug-session.tsx +974 -974
- package/src/browser/debug-tab-bar-decorator.ts +57 -57
- package/src/browser/debug-watch-manager.ts +93 -93
- package/src/browser/disassembly-view/disassembly-view-accessibility-provider.ts +43 -43
- package/src/browser/disassembly-view/disassembly-view-breakpoint-renderer.ts +119 -119
- package/src/browser/disassembly-view/disassembly-view-contribution.ts +109 -109
- package/src/browser/disassembly-view/disassembly-view-instruction-renderer.ts +245 -245
- package/src/browser/disassembly-view/disassembly-view-table-delegate.ts +39 -39
- package/src/browser/disassembly-view/disassembly-view-utilities.ts +55 -55
- package/src/browser/disassembly-view/disassembly-view-widget.ts +463 -463
- package/src/browser/editor/debug-breakpoint-widget.tsx +293 -293
- package/src/browser/editor/debug-editor-model.ts +529 -529
- package/src/browser/editor/debug-editor-service.ts +192 -192
- package/src/browser/editor/debug-editor.ts +20 -20
- package/src/browser/editor/debug-exception-widget.tsx +122 -122
- package/src/browser/editor/debug-expression-provider.ts +78 -78
- package/src/browser/editor/debug-hover-source.tsx +105 -105
- package/src/browser/editor/debug-hover-widget.ts +298 -298
- package/src/browser/editor/debug-inline-value-decorator.ts +373 -373
- package/src/browser/model/debug-breakpoint.tsx +151 -151
- package/src/browser/model/debug-function-breakpoint.tsx +101 -101
- package/src/browser/model/debug-instruction-breakpoint.tsx +68 -68
- package/src/browser/model/debug-source-breakpoint.tsx +237 -237
- package/src/browser/model/debug-source.ts +93 -93
- package/src/browser/model/debug-stack-frame.tsx +177 -177
- package/src/browser/model/debug-thread.tsx +292 -292
- package/src/browser/preferences/launch-preferences.ts +38 -38
- package/src/browser/style/index.css +453 -453
- package/src/browser/view/debug-action.tsx +57 -57
- package/src/browser/view/debug-breakpoints-source.tsx +53 -53
- package/src/browser/view/debug-breakpoints-widget.ts +71 -71
- package/src/browser/view/debug-configuration-select.tsx +269 -269
- package/src/browser/view/debug-configuration-widget.tsx +121 -121
- package/src/browser/view/debug-exception-breakpoint.tsx +68 -68
- package/src/browser/view/debug-session-widget.ts +124 -124
- package/src/browser/view/debug-stack-frames-source.tsx +75 -75
- package/src/browser/view/debug-stack-frames-widget.ts +135 -135
- package/src/browser/view/debug-threads-source.tsx +48 -48
- package/src/browser/view/debug-threads-widget.ts +126 -126
- package/src/browser/view/debug-toolbar-widget.tsx +145 -145
- package/src/browser/view/debug-variables-source.ts +43 -43
- package/src/browser/view/debug-variables-widget.ts +61 -61
- package/src/browser/view/debug-view-model.ts +230 -230
- package/src/browser/view/debug-watch-expression.tsx +88 -88
- package/src/browser/view/debug-watch-source.ts +41 -41
- package/src/browser/view/debug-watch-widget.ts +61 -61
- package/src/browser/view/debug-widget.ts +97 -97
- package/src/common/debug-adapter-contribution-registry.ts +206 -206
- package/src/common/debug-adapter-session.ts +102 -102
- package/src/common/debug-common.ts +19 -19
- package/src/common/debug-compound.ts +33 -33
- package/src/common/debug-configuration.ts +112 -112
- package/src/common/debug-model.ts +200 -200
- package/src/common/debug-service.ts +184 -184
- package/src/common/debug-uri-utils.ts +24 -24
- package/src/common/inline-debug-adapter.ts +47 -47
- package/src/node/debug-adapter-factory.ts +107 -107
- package/src/node/debug-adapter-session-manager.ts +106 -106
- package/src/node/debug-backend-module.ts +57 -57
- package/src/node/debug-service-impl.ts +119 -119
- package/src/node/stream-debug-adapter.ts +126 -126
|
@@ -1,122 +1,122 @@
|
|
|
1
|
-
// *****************************************************************************
|
|
2
|
-
// Copyright (C) 2019 TypeFox and others.
|
|
3
|
-
//
|
|
4
|
-
// This program and the accompanying materials are made available under the
|
|
5
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
-
//
|
|
8
|
-
// This Source Code may also be made available under the following Secondary
|
|
9
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
-
// with the GNU Classpath Exception which is available at
|
|
12
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
-
//
|
|
14
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
-
// *****************************************************************************
|
|
16
|
-
|
|
17
|
-
import * as React from '@theia/core/shared/react';
|
|
18
|
-
import { createRoot, Root } from '@theia/core/shared/react-dom/client';
|
|
19
|
-
import * as monaco from '@theia/monaco-editor-core';
|
|
20
|
-
import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
|
|
21
|
-
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
|
|
22
|
-
import { MonacoEditorZoneWidget } from '@theia/monaco/lib/browser/monaco-editor-zone-widget';
|
|
23
|
-
import { DebugEditor } from './debug-editor';
|
|
24
|
-
import { DebugExceptionInfo } from '../model/debug-thread';
|
|
25
|
-
import { nls } from '@theia/core/lib/common/nls';
|
|
26
|
-
import { codicon } from '@theia/core/lib/browser/widgets';
|
|
27
|
-
|
|
28
|
-
export interface ShowDebugExceptionParams {
|
|
29
|
-
info: DebugExceptionInfo
|
|
30
|
-
lineNumber: number
|
|
31
|
-
column: number
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class DebugExceptionMonacoEditorZoneWidget extends MonacoEditorZoneWidget {
|
|
35
|
-
|
|
36
|
-
protected override computeContainerHeight(zoneHeight: number): {
|
|
37
|
-
height: number,
|
|
38
|
-
frameWidth: number
|
|
39
|
-
} {
|
|
40
|
-
// reset height to match it to the content
|
|
41
|
-
this.containerNode.style.height = 'initial';
|
|
42
|
-
const height = this.containerNode.offsetHeight;
|
|
43
|
-
const result = super.computeContainerHeight(zoneHeight);
|
|
44
|
-
result.height = height;
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@injectable()
|
|
51
|
-
export class DebugExceptionWidget implements Disposable {
|
|
52
|
-
|
|
53
|
-
@inject(DebugEditor)
|
|
54
|
-
readonly editor: DebugEditor;
|
|
55
|
-
|
|
56
|
-
protected zone: MonacoEditorZoneWidget;
|
|
57
|
-
protected containerNodeRoot: Root;
|
|
58
|
-
|
|
59
|
-
protected readonly toDispose = new DisposableCollection();
|
|
60
|
-
|
|
61
|
-
@postConstruct()
|
|
62
|
-
protected init(): void {
|
|
63
|
-
this.doInit();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
protected async doInit(): Promise<void> {
|
|
67
|
-
this.toDispose.push(this.zone = new DebugExceptionMonacoEditorZoneWidget(this.editor.getControl()));
|
|
68
|
-
this.zone.containerNode.classList.add('theia-debug-exception-widget');
|
|
69
|
-
this.containerNodeRoot = createRoot(this.zone.containerNode);
|
|
70
|
-
this.toDispose.push(Disposable.create(() => this.containerNodeRoot.unmount()));
|
|
71
|
-
this.toDispose.push(this.editor.getControl().onDidLayoutChange(() => this.layout()));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
dispose(): void {
|
|
75
|
-
this.toDispose.dispose();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
show({ info, lineNumber, column }: ShowDebugExceptionParams): void {
|
|
79
|
-
this.render(info, () => {
|
|
80
|
-
const fontInfo = this.editor.getControl().getOption(monaco.editor.EditorOption.fontInfo);
|
|
81
|
-
this.zone.containerNode.style.fontSize = `${fontInfo.fontSize}px`;
|
|
82
|
-
this.zone.containerNode.style.lineHeight = `${fontInfo.lineHeight}px`;
|
|
83
|
-
|
|
84
|
-
if (lineNumber !== undefined && column !== undefined) {
|
|
85
|
-
const afterLineNumber = lineNumber;
|
|
86
|
-
const afterColumn = column;
|
|
87
|
-
this.zone.show({ showFrame: true, afterLineNumber, afterColumn, heightInLines: 0, frameWidth: 1 });
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
this.layout();
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
hide(): void {
|
|
95
|
-
this.zone.hide();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
protected render(info: DebugExceptionInfo, cb: () => void): void {
|
|
99
|
-
const stackTrace = info.details && info.details.stackTrace;
|
|
100
|
-
const exceptionTitle = info.id ?
|
|
101
|
-
nls.localizeByDefault('Exception has occurred: {0}', info.id) :
|
|
102
|
-
nls.localizeByDefault('Exception has occurred.');
|
|
103
|
-
this.containerNodeRoot.render(<React.Fragment>
|
|
104
|
-
<div className='title' ref={cb}>
|
|
105
|
-
{exceptionTitle}
|
|
106
|
-
<span id="exception-close" className={codicon('close', true)} onClick={() => this.hide()} title={nls.localizeByDefault('Close')}></span>
|
|
107
|
-
</div>
|
|
108
|
-
{info.description && <div className='description'>{info.description}</div>}
|
|
109
|
-
{stackTrace && <div className='stack-trace'>{stackTrace}</div>}
|
|
110
|
-
</React.Fragment>);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
protected layout(): void {
|
|
114
|
-
// reset height to match it to the content
|
|
115
|
-
this.zone.containerNode.style.height = 'initial';
|
|
116
|
-
|
|
117
|
-
const lineHeight = this.editor.getControl().getOption(monaco.editor.EditorOption.lineHeight);
|
|
118
|
-
const heightInLines = Math.ceil(this.zone.containerNode.offsetHeight / lineHeight);
|
|
119
|
-
this.zone.layout(heightInLines);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
}
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2019 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import * as React from '@theia/core/shared/react';
|
|
18
|
+
import { createRoot, Root } from '@theia/core/shared/react-dom/client';
|
|
19
|
+
import * as monaco from '@theia/monaco-editor-core';
|
|
20
|
+
import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
|
|
21
|
+
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
|
|
22
|
+
import { MonacoEditorZoneWidget } from '@theia/monaco/lib/browser/monaco-editor-zone-widget';
|
|
23
|
+
import { DebugEditor } from './debug-editor';
|
|
24
|
+
import { DebugExceptionInfo } from '../model/debug-thread';
|
|
25
|
+
import { nls } from '@theia/core/lib/common/nls';
|
|
26
|
+
import { codicon } from '@theia/core/lib/browser/widgets';
|
|
27
|
+
|
|
28
|
+
export interface ShowDebugExceptionParams {
|
|
29
|
+
info: DebugExceptionInfo
|
|
30
|
+
lineNumber: number
|
|
31
|
+
column: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class DebugExceptionMonacoEditorZoneWidget extends MonacoEditorZoneWidget {
|
|
35
|
+
|
|
36
|
+
protected override computeContainerHeight(zoneHeight: number): {
|
|
37
|
+
height: number,
|
|
38
|
+
frameWidth: number
|
|
39
|
+
} {
|
|
40
|
+
// reset height to match it to the content
|
|
41
|
+
this.containerNode.style.height = 'initial';
|
|
42
|
+
const height = this.containerNode.offsetHeight;
|
|
43
|
+
const result = super.computeContainerHeight(zoneHeight);
|
|
44
|
+
result.height = height;
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@injectable()
|
|
51
|
+
export class DebugExceptionWidget implements Disposable {
|
|
52
|
+
|
|
53
|
+
@inject(DebugEditor)
|
|
54
|
+
readonly editor: DebugEditor;
|
|
55
|
+
|
|
56
|
+
protected zone: MonacoEditorZoneWidget;
|
|
57
|
+
protected containerNodeRoot: Root;
|
|
58
|
+
|
|
59
|
+
protected readonly toDispose = new DisposableCollection();
|
|
60
|
+
|
|
61
|
+
@postConstruct()
|
|
62
|
+
protected init(): void {
|
|
63
|
+
this.doInit();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
protected async doInit(): Promise<void> {
|
|
67
|
+
this.toDispose.push(this.zone = new DebugExceptionMonacoEditorZoneWidget(this.editor.getControl()));
|
|
68
|
+
this.zone.containerNode.classList.add('theia-debug-exception-widget');
|
|
69
|
+
this.containerNodeRoot = createRoot(this.zone.containerNode);
|
|
70
|
+
this.toDispose.push(Disposable.create(() => this.containerNodeRoot.unmount()));
|
|
71
|
+
this.toDispose.push(this.editor.getControl().onDidLayoutChange(() => this.layout()));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
dispose(): void {
|
|
75
|
+
this.toDispose.dispose();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
show({ info, lineNumber, column }: ShowDebugExceptionParams): void {
|
|
79
|
+
this.render(info, () => {
|
|
80
|
+
const fontInfo = this.editor.getControl().getOption(monaco.editor.EditorOption.fontInfo);
|
|
81
|
+
this.zone.containerNode.style.fontSize = `${fontInfo.fontSize}px`;
|
|
82
|
+
this.zone.containerNode.style.lineHeight = `${fontInfo.lineHeight}px`;
|
|
83
|
+
|
|
84
|
+
if (lineNumber !== undefined && column !== undefined) {
|
|
85
|
+
const afterLineNumber = lineNumber;
|
|
86
|
+
const afterColumn = column;
|
|
87
|
+
this.zone.show({ showFrame: true, afterLineNumber, afterColumn, heightInLines: 0, frameWidth: 1 });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this.layout();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
hide(): void {
|
|
95
|
+
this.zone.hide();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected render(info: DebugExceptionInfo, cb: () => void): void {
|
|
99
|
+
const stackTrace = info.details && info.details.stackTrace;
|
|
100
|
+
const exceptionTitle = info.id ?
|
|
101
|
+
nls.localizeByDefault('Exception has occurred: {0}', info.id) :
|
|
102
|
+
nls.localizeByDefault('Exception has occurred.');
|
|
103
|
+
this.containerNodeRoot.render(<React.Fragment>
|
|
104
|
+
<div className='title' ref={cb}>
|
|
105
|
+
{exceptionTitle}
|
|
106
|
+
<span id="exception-close" className={codicon('close', true)} onClick={() => this.hide()} title={nls.localizeByDefault('Close')}></span>
|
|
107
|
+
</div>
|
|
108
|
+
{info.description && <div className='description'>{info.description}</div>}
|
|
109
|
+
{stackTrace && <div className='stack-trace'>{stackTrace}</div>}
|
|
110
|
+
</React.Fragment>);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
protected layout(): void {
|
|
114
|
+
// reset height to match it to the content
|
|
115
|
+
this.zone.containerNode.style.height = 'initial';
|
|
116
|
+
|
|
117
|
+
const lineHeight = this.editor.getControl().getOption(monaco.editor.EditorOption.lineHeight);
|
|
118
|
+
const heightInLines = Math.ceil(this.zone.containerNode.offsetHeight / lineHeight);
|
|
119
|
+
this.zone.layout(heightInLines);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
}
|
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
// *****************************************************************************
|
|
2
|
-
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
-
//
|
|
4
|
-
// This program and the accompanying materials are made available under the
|
|
5
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
-
//
|
|
8
|
-
// This Source Code may also be made available under the following Secondary
|
|
9
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
-
// with the GNU Classpath Exception which is available at
|
|
12
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
-
//
|
|
14
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
-
// *****************************************************************************
|
|
16
|
-
/*---------------------------------------------------------------------------------------------
|
|
17
|
-
* Copyright (c) Microsoft Corporation and others. All rights reserved.
|
|
18
|
-
* Licensed under the MIT License. See https://github.com/Microsoft/vscode/blob/master/LICENSE.txt for license information.
|
|
19
|
-
*--------------------------------------------------------------------------------------------*/
|
|
20
|
-
|
|
21
|
-
import { injectable } from '@theia/core/shared/inversify';
|
|
22
|
-
import * as monaco from '@theia/monaco-editor-core';
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* TODO: introduce a new request to LSP to look up an expression range: https://github.com/Microsoft/language-server-protocol/issues/462
|
|
26
|
-
*/
|
|
27
|
-
@injectable()
|
|
28
|
-
export class DebugExpressionProvider {
|
|
29
|
-
get(model: monaco.editor.IModel, selection: monaco.IRange): string {
|
|
30
|
-
const lineContent = model.getLineContent(selection.startLineNumber);
|
|
31
|
-
const { start, end } = this.getExactExpressionStartAndEnd(lineContent, selection.startColumn, selection.endColumn);
|
|
32
|
-
return lineContent.substring(start - 1, end);
|
|
33
|
-
}
|
|
34
|
-
protected getExactExpressionStartAndEnd(lineContent: string, looseStart: number, looseEnd: number): { start: number, end: number } {
|
|
35
|
-
let matchingExpression: string | undefined = undefined;
|
|
36
|
-
let startOffset = 0;
|
|
37
|
-
|
|
38
|
-
// Some example supported expressions: myVar.prop, a.b.c.d, myVar?.prop, myVar->prop, MyClass::StaticProp, *myVar
|
|
39
|
-
// Match any character except a set of characters which often break interesting sub-expressions
|
|
40
|
-
const expression = /([^()\[\]{}<>\s+\-/%~#^;=|,`!]|\->)+/g;
|
|
41
|
-
// eslint-disable-next-line no-null/no-null
|
|
42
|
-
let result: RegExpExecArray | null = null;
|
|
43
|
-
|
|
44
|
-
// First find the full expression under the cursor
|
|
45
|
-
while (result = expression.exec(lineContent)) {
|
|
46
|
-
const start = result.index + 1;
|
|
47
|
-
const end = start + result[0].length;
|
|
48
|
-
|
|
49
|
-
if (start <= looseStart && end >= looseEnd) {
|
|
50
|
-
matchingExpression = result[0];
|
|
51
|
-
startOffset = start;
|
|
52
|
-
break;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// If there are non-word characters after the cursor, we want to truncate the expression then.
|
|
57
|
-
// For example in expression 'a.b.c.d', if the focus was under 'b', 'a.b' would be evaluated.
|
|
58
|
-
if (matchingExpression) {
|
|
59
|
-
const subExpression: RegExp = /\w+/g;
|
|
60
|
-
// eslint-disable-next-line no-null/no-null
|
|
61
|
-
let subExpressionResult: RegExpExecArray | null = null;
|
|
62
|
-
while (subExpressionResult = subExpression.exec(matchingExpression)) {
|
|
63
|
-
const subEnd = subExpressionResult.index + 1 + startOffset + subExpressionResult[0].length;
|
|
64
|
-
if (subEnd >= looseEnd) {
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (subExpressionResult) {
|
|
70
|
-
matchingExpression = matchingExpression.substring(0, subExpression.lastIndex);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return matchingExpression ?
|
|
75
|
-
{ start: startOffset, end: startOffset + matchingExpression.length - 1 } :
|
|
76
|
-
{ start: 0, end: 0 };
|
|
77
|
-
}
|
|
78
|
-
}
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
/*---------------------------------------------------------------------------------------------
|
|
17
|
+
* Copyright (c) Microsoft Corporation and others. All rights reserved.
|
|
18
|
+
* Licensed under the MIT License. See https://github.com/Microsoft/vscode/blob/master/LICENSE.txt for license information.
|
|
19
|
+
*--------------------------------------------------------------------------------------------*/
|
|
20
|
+
|
|
21
|
+
import { injectable } from '@theia/core/shared/inversify';
|
|
22
|
+
import * as monaco from '@theia/monaco-editor-core';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* TODO: introduce a new request to LSP to look up an expression range: https://github.com/Microsoft/language-server-protocol/issues/462
|
|
26
|
+
*/
|
|
27
|
+
@injectable()
|
|
28
|
+
export class DebugExpressionProvider {
|
|
29
|
+
get(model: monaco.editor.IModel, selection: monaco.IRange): string {
|
|
30
|
+
const lineContent = model.getLineContent(selection.startLineNumber);
|
|
31
|
+
const { start, end } = this.getExactExpressionStartAndEnd(lineContent, selection.startColumn, selection.endColumn);
|
|
32
|
+
return lineContent.substring(start - 1, end);
|
|
33
|
+
}
|
|
34
|
+
protected getExactExpressionStartAndEnd(lineContent: string, looseStart: number, looseEnd: number): { start: number, end: number } {
|
|
35
|
+
let matchingExpression: string | undefined = undefined;
|
|
36
|
+
let startOffset = 0;
|
|
37
|
+
|
|
38
|
+
// Some example supported expressions: myVar.prop, a.b.c.d, myVar?.prop, myVar->prop, MyClass::StaticProp, *myVar
|
|
39
|
+
// Match any character except a set of characters which often break interesting sub-expressions
|
|
40
|
+
const expression = /([^()\[\]{}<>\s+\-/%~#^;=|,`!]|\->)+/g;
|
|
41
|
+
// eslint-disable-next-line no-null/no-null
|
|
42
|
+
let result: RegExpExecArray | null = null;
|
|
43
|
+
|
|
44
|
+
// First find the full expression under the cursor
|
|
45
|
+
while (result = expression.exec(lineContent)) {
|
|
46
|
+
const start = result.index + 1;
|
|
47
|
+
const end = start + result[0].length;
|
|
48
|
+
|
|
49
|
+
if (start <= looseStart && end >= looseEnd) {
|
|
50
|
+
matchingExpression = result[0];
|
|
51
|
+
startOffset = start;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// If there are non-word characters after the cursor, we want to truncate the expression then.
|
|
57
|
+
// For example in expression 'a.b.c.d', if the focus was under 'b', 'a.b' would be evaluated.
|
|
58
|
+
if (matchingExpression) {
|
|
59
|
+
const subExpression: RegExp = /\w+/g;
|
|
60
|
+
// eslint-disable-next-line no-null/no-null
|
|
61
|
+
let subExpressionResult: RegExpExecArray | null = null;
|
|
62
|
+
while (subExpressionResult = subExpression.exec(matchingExpression)) {
|
|
63
|
+
const subEnd = subExpressionResult.index + 1 + startOffset + subExpressionResult[0].length;
|
|
64
|
+
if (subEnd >= looseEnd) {
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (subExpressionResult) {
|
|
70
|
+
matchingExpression = matchingExpression.substring(0, subExpression.lastIndex);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return matchingExpression ?
|
|
75
|
+
{ start: startOffset, end: startOffset + matchingExpression.length - 1 } :
|
|
76
|
+
{ start: 0, end: 0 };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
// *****************************************************************************
|
|
2
|
-
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
-
//
|
|
4
|
-
// This program and the accompanying materials are made available under the
|
|
5
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
-
//
|
|
8
|
-
// This Source Code may also be made available under the following Secondary
|
|
9
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
-
// with the GNU Classpath Exception which is available at
|
|
12
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
-
//
|
|
14
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
-
// *****************************************************************************
|
|
16
|
-
|
|
17
|
-
import * as React from '@theia/core/shared/react';
|
|
18
|
-
import { TreeSource, TreeElement } from '@theia/core/lib/browser/source-tree';
|
|
19
|
-
import { ExpressionContainer, ExpressionItem, DebugVariable } from '../console/debug-console-items';
|
|
20
|
-
import { DebugSessionManager } from '../debug-session-manager';
|
|
21
|
-
import { injectable, inject } from '@theia/core/shared/inversify';
|
|
22
|
-
|
|
23
|
-
@injectable()
|
|
24
|
-
export class DebugHoverSource extends TreeSource {
|
|
25
|
-
|
|
26
|
-
@inject(DebugSessionManager)
|
|
27
|
-
protected readonly sessions: DebugSessionManager;
|
|
28
|
-
|
|
29
|
-
protected _expression: ExpressionItem | DebugVariable | undefined;
|
|
30
|
-
get expression(): ExpressionItem | DebugVariable | undefined {
|
|
31
|
-
return this._expression;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
protected elements: TreeElement[] = [];
|
|
35
|
-
getElements(): IterableIterator<TreeElement> {
|
|
36
|
-
return this.elements[Symbol.iterator]();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
protected renderTitle(element: ExpressionItem | DebugVariable): React.ReactNode {
|
|
40
|
-
return <div className='theia-debug-hover-title' title={element.value}>{element.value}</div>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
reset(): void {
|
|
44
|
-
this._expression = undefined;
|
|
45
|
-
this.elements = [];
|
|
46
|
-
this.fireDidChange();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async evaluate(expression: string): Promise<ExpressionItem | DebugVariable | undefined> {
|
|
50
|
-
const evaluated = await this.doEvaluate(expression);
|
|
51
|
-
const elements = evaluated && await evaluated.getElements();
|
|
52
|
-
this._expression = evaluated;
|
|
53
|
-
this.elements = elements ? [...elements] : [];
|
|
54
|
-
this.fireDidChange();
|
|
55
|
-
return evaluated;
|
|
56
|
-
}
|
|
57
|
-
protected async doEvaluate(expression: string): Promise<ExpressionItem | DebugVariable | undefined> {
|
|
58
|
-
const { currentSession } = this.sessions;
|
|
59
|
-
if (!currentSession) {
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
if (currentSession.capabilities.supportsEvaluateForHovers) {
|
|
63
|
-
const item = new ExpressionItem(expression, () => currentSession);
|
|
64
|
-
await item.evaluate('hover');
|
|
65
|
-
return item.available && item || undefined;
|
|
66
|
-
}
|
|
67
|
-
return this.findVariable(expression.split('.').map(word => word.trim()).filter(word => !!word));
|
|
68
|
-
}
|
|
69
|
-
protected async findVariable(namesToFind: string[]): Promise<DebugVariable | undefined> {
|
|
70
|
-
const { currentFrame } = this.sessions;
|
|
71
|
-
if (!currentFrame) {
|
|
72
|
-
return undefined;
|
|
73
|
-
}
|
|
74
|
-
let variable: DebugVariable | undefined;
|
|
75
|
-
const scopes = await currentFrame.getScopes();
|
|
76
|
-
for (const scope of scopes) {
|
|
77
|
-
const found = await this.doFindVariable(scope, namesToFind);
|
|
78
|
-
if (!variable) {
|
|
79
|
-
variable = found;
|
|
80
|
-
} else if (found && found.value !== variable.value) {
|
|
81
|
-
// only show if all expressions found have the same value
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return variable;
|
|
86
|
-
}
|
|
87
|
-
protected async doFindVariable(owner: ExpressionContainer, namesToFind: string[]): Promise<DebugVariable | undefined> {
|
|
88
|
-
const elements = await owner.getElements();
|
|
89
|
-
const variables: DebugVariable[] = [];
|
|
90
|
-
for (const element of elements) {
|
|
91
|
-
if (element instanceof DebugVariable && element.name === namesToFind[0]) {
|
|
92
|
-
variables.push(element);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (variables.length !== 1) {
|
|
96
|
-
return undefined;
|
|
97
|
-
}
|
|
98
|
-
if (namesToFind.length === 1) {
|
|
99
|
-
return variables[0];
|
|
100
|
-
} else {
|
|
101
|
-
return this.doFindVariable(variables[0], namesToFind.slice(1));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
}
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2018 TypeFox and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import * as React from '@theia/core/shared/react';
|
|
18
|
+
import { TreeSource, TreeElement } from '@theia/core/lib/browser/source-tree';
|
|
19
|
+
import { ExpressionContainer, ExpressionItem, DebugVariable } from '../console/debug-console-items';
|
|
20
|
+
import { DebugSessionManager } from '../debug-session-manager';
|
|
21
|
+
import { injectable, inject } from '@theia/core/shared/inversify';
|
|
22
|
+
|
|
23
|
+
@injectable()
|
|
24
|
+
export class DebugHoverSource extends TreeSource {
|
|
25
|
+
|
|
26
|
+
@inject(DebugSessionManager)
|
|
27
|
+
protected readonly sessions: DebugSessionManager;
|
|
28
|
+
|
|
29
|
+
protected _expression: ExpressionItem | DebugVariable | undefined;
|
|
30
|
+
get expression(): ExpressionItem | DebugVariable | undefined {
|
|
31
|
+
return this._expression;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected elements: TreeElement[] = [];
|
|
35
|
+
getElements(): IterableIterator<TreeElement> {
|
|
36
|
+
return this.elements[Symbol.iterator]();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected renderTitle(element: ExpressionItem | DebugVariable): React.ReactNode {
|
|
40
|
+
return <div className='theia-debug-hover-title' title={element.value}>{element.value}</div>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
reset(): void {
|
|
44
|
+
this._expression = undefined;
|
|
45
|
+
this.elements = [];
|
|
46
|
+
this.fireDidChange();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async evaluate(expression: string): Promise<ExpressionItem | DebugVariable | undefined> {
|
|
50
|
+
const evaluated = await this.doEvaluate(expression);
|
|
51
|
+
const elements = evaluated && await evaluated.getElements();
|
|
52
|
+
this._expression = evaluated;
|
|
53
|
+
this.elements = elements ? [...elements] : [];
|
|
54
|
+
this.fireDidChange();
|
|
55
|
+
return evaluated;
|
|
56
|
+
}
|
|
57
|
+
protected async doEvaluate(expression: string): Promise<ExpressionItem | DebugVariable | undefined> {
|
|
58
|
+
const { currentSession } = this.sessions;
|
|
59
|
+
if (!currentSession) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
if (currentSession.capabilities.supportsEvaluateForHovers) {
|
|
63
|
+
const item = new ExpressionItem(expression, () => currentSession);
|
|
64
|
+
await item.evaluate('hover');
|
|
65
|
+
return item.available && item || undefined;
|
|
66
|
+
}
|
|
67
|
+
return this.findVariable(expression.split('.').map(word => word.trim()).filter(word => !!word));
|
|
68
|
+
}
|
|
69
|
+
protected async findVariable(namesToFind: string[]): Promise<DebugVariable | undefined> {
|
|
70
|
+
const { currentFrame } = this.sessions;
|
|
71
|
+
if (!currentFrame) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
let variable: DebugVariable | undefined;
|
|
75
|
+
const scopes = await currentFrame.getScopes();
|
|
76
|
+
for (const scope of scopes) {
|
|
77
|
+
const found = await this.doFindVariable(scope, namesToFind);
|
|
78
|
+
if (!variable) {
|
|
79
|
+
variable = found;
|
|
80
|
+
} else if (found && found.value !== variable.value) {
|
|
81
|
+
// only show if all expressions found have the same value
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return variable;
|
|
86
|
+
}
|
|
87
|
+
protected async doFindVariable(owner: ExpressionContainer, namesToFind: string[]): Promise<DebugVariable | undefined> {
|
|
88
|
+
const elements = await owner.getElements();
|
|
89
|
+
const variables: DebugVariable[] = [];
|
|
90
|
+
for (const element of elements) {
|
|
91
|
+
if (element instanceof DebugVariable && element.name === namesToFind[0]) {
|
|
92
|
+
variables.push(element);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (variables.length !== 1) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (namesToFind.length === 1) {
|
|
99
|
+
return variables[0];
|
|
100
|
+
} else {
|
|
101
|
+
return this.doFindVariable(variables[0], namesToFind.slice(1));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
}
|