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 custom view for easy access to the Rascal debugger #564

Merged
merged 26 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b54a243
Created custom view listing Rascal REPLs for better interaction with …
rodinaarssen Jan 23, 2025
45cfa49
Merge remote-tracking branch 'origin' into debugger-ux
rodinaarssen Jan 23, 2025
9351f4f
Changed function signature
rodinaarssen Jan 28, 2025
6c65a03
Removed debug prints
rodinaarssen Jan 28, 2025
01035c7
Removed more debug prints
rodinaarssen Jan 28, 2025
07418db
Reduced number of commands and simplified logic
rodinaarssen Jan 28, 2025
4320b9e
Using debug logo in Rascal debug view
rodinaarssen Jan 28, 2025
cbbb04f
Added command for updating debug view upon registering debug port
rodinaarssen Jan 28, 2025
77cd7c1
Using debug icon for view
rodinaarssen Jan 28, 2025
1e13fc8
Merge remote-tracking branch 'origin/main' into debugger-ux
rodinaarssen Jan 28, 2025
cd479cd
Changed name of Rascal debug view
rodinaarssen Jan 28, 2025
122a95b
Added terminal or debug icon in front of every entry in the Rascal de…
rodinaarssen Jan 28, 2025
25ac3f8
Prevent debug command from showing up in the command palette
rodinaarssen Jan 30, 2025
65197d5
Improved constructor of RascalReplNode
rodinaarssen Jan 30, 2025
3f9cc88
Moved registration of the debug command
rodinaarssen Jan 30, 2025
3a41a23
Removed the debug command from package.json and updated logic corresp…
rodinaarssen Jan 30, 2025
603a52d
Added comment
rodinaarssen Jan 30, 2025
2580d9f
Revert "Removed the debug command from package.json and updated logic…
rodinaarssen Jan 30, 2025
d4b0aac
Fixed type
rodinaarssen Jan 30, 2025
6a1a8a7
Using Event instead of internal command
rodinaarssen Jan 30, 2025
57352e6
Merge remote-tracking branch 'origin/main' into debugger-ux
rodinaarssen Jan 30, 2025
484fd1f
Updated year in license
rodinaarssen Jan 30, 2025
01b45fd
Refactored subscriptions to be an argument
rodinaarssen Jan 30, 2025
a644b26
Removed spurious assignment in constructor
rodinaarssen Jan 30, 2025
f640a5b
Improved logic around checking whether a terminal is currently active
rodinaarssen Jan 30, 2025
9c0440b
Added payload to debug event
rodinaarssen Jan 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions rascal-vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,22 @@
{
"command": "rascalmpl.importModule",
"title": "Start Rascal Terminal and Import this module"
},
{
"command": "rascalmpl.startDebuggerForRepl",
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
"title": "Start Rascal debugger for REPL",
"icon": "$(debug)"
}
],
"menus": {
"view/item/context": [
{
"command": "rascalmpl.startDebuggerForRepl",
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
"when": "view == rascalmpl-debugger-view && viewItem == 'canStartDebugging'",
"group": "inline"
}
]
},
"languages": [
{
"id": "rascalmpl",
Expand Down Expand Up @@ -89,12 +103,24 @@
"icon": "./assets/images/rascal-logo-v2.1.svg",
"visibility": "collapsed"
}
],
"debug": [
{
"id": "rascalmpl-debugger-view",
"name": "Debug Rascal Terminal",
"icon": "$(debug)",
"visibility": "visible"
}
]
},
"viewsWelcome": [
{
"view": "rascalmpl-configuration-view",
"contents": "No Rascal Projects found in the workspace"
},
{
"view": "rascalmpl-debugger-view",
"contents": "No active Rascal REPLs found"
}
],
"breakpoints": [
Expand Down
13 changes: 13 additions & 0 deletions rascal-vscode-extension/src/RascalExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { RascalTerminalLinkProvider } from './RascalTerminalLinkProvider';
import { VSCodeUriResolverServer } from './fs/VSCodeURIResolver';
import { RascalLibraryProvider } from './ux/LibraryNavigator';
import { FileType } from 'vscode';
import { RascalReplNode, RascalDebugViewProvider } from './dap/RascalDebugView';

export class RascalExtension implements vscode.Disposable {
private readonly vfsServer: VSCodeUriResolverServer;
Expand All @@ -52,9 +53,11 @@ export class RascalExtension implements vscode.Disposable {
this.registerTerminalCommand();
this.registerMainRun();
this.registerImportModule();
this.registerDebuggerCommand();
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
checkForJVMUpdate();

vscode.window.registerTreeDataProvider('rascalmpl-configuration-view', new RascalLibraryProvider(this.rascal.rascalClient));
vscode.window.registerTreeDataProvider('rascalmpl-debugger-view', new RascalDebugViewProvider(this.rascal.rascalDebugClient, context));
vscode.window.registerTerminalLinkProvider(new RascalTerminalLinkProvider(this.rascal.rascalClient));
}

Expand Down Expand Up @@ -103,6 +106,16 @@ export class RascalExtension implements vscode.Disposable {
);
}

private registerDebuggerCommand() {
this.context.subscriptions.push(
vscode.commands.registerCommand("rascalmpl.startDebuggerForRepl", (replNode: RascalReplNode) => {
if (replNode.serverPort !== undefined) {
this.rascal.rascalDebugClient.startDebuggingSession(replNode.serverPort);
}
})
);
}

private async startTerminal(uri: vscode.Uri | undefined, ...extraArgs: string[]) {
try {
await vscode.window.withProgress({
Expand Down
10 changes: 4 additions & 6 deletions rascal-vscode-extension/src/dap/RascalDebugClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import { debug, DebugConfiguration, DebugSession, Terminal, window } from "vscode";
import { debug, DebugConfiguration, DebugSession, Terminal, window, commands } from "vscode";
import { RascalDebugAdapterDescriptorFactory } from "./RascalDebugAdapterDescriptorFactory";
import { RascalDebugConfigurationProvider } from "./RascalDebugConfigurationProvider";

Expand Down Expand Up @@ -77,13 +77,11 @@ export class RascalDebugClient {

registerDebugServerPort(processID: number, serverPort: number){
this.debugSocketServersPorts.set(processID, serverPort);
commands.executeCommand('rascalmpl.updateDebugView');
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
}

getServerPort(processID: number | undefined){
if(processID !== undefined && this.debugSocketServersPorts.has(processID)){
return this.debugSocketServersPorts.get(processID);
}
return undefined;
getServerPort(processId: number){
return this.debugSocketServersPorts.get(processId);
}

isConnectedToDebugServer(serverPort: number){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ export class RascalDebugConfigurationProvider implements DebugConfigurationProvi

if (!debugConfiguration['serverPort']){
const terminalProcessID = await window.activeTerminal?.processId;
if (terminalProcessID === undefined) {
throw Error("Active terminal has no associated process ID!");
}
const port = this.debugClient.getServerPort(terminalProcessID);
if(port === undefined) {
throw Error("Active terminal has not a debug server port registered !");
Expand Down
120 changes: 120 additions & 0 deletions rascal-vscode-extension/src/dap/RascalDebugView.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (c) 2018-2023, NWO-I CWI and Swat.engineering
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import * as vscode from 'vscode';
import { RascalDebugClient } from './RascalDebugClient';

export class RascalDebugViewProvider implements vscode.TreeDataProvider<RascalReplNode> {
private changeEmitter = new vscode.EventEmitter<RascalReplNode | undefined>();
readonly onDidChangeTreeData = this.changeEmitter.event;

constructor(private readonly rascalDebugClient: RascalDebugClient, readonly context: vscode.ExtensionContext) {
vscode.window.onDidOpenTerminal(_e => {
this.changeEmitter.fire(undefined);
});
vscode.window.onDidCloseTerminal(_e => {
this.changeEmitter.fire(undefined);
});
vscode.window.onDidChangeActiveTerminal(_e => {
this.changeEmitter.fire(undefined);
});
vscode.debug.onDidStartDebugSession(_e => {
this.changeEmitter.fire(undefined);
});
vscode.debug.onDidTerminateDebugSession(_e => {
this.changeEmitter.fire(undefined);
});
vscode.debug.onDidReceiveDebugSessionCustomEvent(_e => {
this.changeEmitter.fire(undefined);
});
context.subscriptions.push(vscode.commands.registerCommand('rascalmpl.updateDebugView', () => {
this.changeEmitter.fire(undefined);
}));
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
}

getTreeItem(element: RascalReplNode): vscode.TreeItem | Thenable<vscode.TreeItem> {
return element;
}
getChildren(element?: RascalReplNode | undefined): vscode.ProviderResult<RascalReplNode[]> {
if (element === undefined) {
return this.updateRascalDebugView();
}
return [];
}
getParent?(_element: RascalReplNode): vscode.ProviderResult<RascalReplNode> {
return undefined;
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
}
resolveTreeItem?(item: vscode.TreeItem, _element: RascalReplNode, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.TreeItem> {
return item;
}

async makeLabel(label: string, processId : number) : Promise<string | vscode.TreeItemLabel> {
if (await this.isActiveTerminal(processId)) {
return {label: label, highlights : [[0, label.length]]};
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
}
return label;
}

async updateRascalDebugView() : Promise<vscode.TreeItem[]> {
const result : RascalReplNode[] = [];
for (const terminal of vscode.window.terminals) {
const processId = await terminal.processId;
if (processId === undefined) {
continue;
}
if (terminal.name.includes("Rascal terminal")) {
const label = await this.makeLabel(terminal.name, processId);
const serverPort = this.rascalDebugClient.getServerPort(processId);
const isDebugging = serverPort !== undefined && this.rascalDebugClient.isConnectedToDebugServer(serverPort);
const replNode = new RascalReplNode(label, serverPort, isDebugging);
if (serverPort !== undefined && !isDebugging) {
replNode.contextValue = "canStartDebugging";
}
result.push(replNode);
}
}
return result;
}

async isActiveTerminal(processId : number) : Promise<boolean> {
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
const activeTerminal = vscode.window.activeTerminal;
if (activeTerminal === undefined) {
return false;
}
return processId === await activeTerminal.processId;
}

}

export class RascalReplNode extends vscode.TreeItem {
serverPort? : number | undefined;

constructor(label : string | vscode.TreeItemLabel, serverPort : number | undefined, isDebugging : boolean) {
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
super(label, vscode.TreeItemCollapsibleState.None);
this.serverPort = serverPort;
rodinaarssen marked this conversation as resolved.
Show resolved Hide resolved
this.iconPath = new vscode.ThemeIcon(isDebugging ? "debug" : "terminal");
}
}
Loading