Skip to content

Commit c8dfd42

Browse files
mlaukesmokku
andauthored
feat: source file resolving relative to workspace and provided srcDirs
* +fix: source file resolving if debugee is located in subdir +fix: error message handling +feat: add steckschwein to list of emulators supporting cc65-dbg * +fix: resolve workspace file from source in .dbg file * +feat: revision source base path lookup to work with debugees within sub directory +feat: support for additional src directories via srcDirs launch confifuration property - e.g. used for cc65 library source lookup path * +update doc * +fix: clean code * +fix: more clean * +feat: steckschwein icon * Update src/cc65Debug.ts Co-authored-by: Tomasz Sterna <tomasz@sterna.link> * +fix: source path resolving and file ambiguity (thx to smokku for the advise) * +fix: whitespace --------- Co-authored-by: Tomasz Sterna <tomasz@sterna.link>
1 parent b33f3a1 commit c8dfd42

3 files changed

Lines changed: 43 additions & 6 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ To start the emulator and begin debugging automatically:
6666
"args": ["--dap"],
6767
"stopOnEntry": true,
6868
"cwd": "${workspaceFolder}",
69+
"srcDirs": ["${workspaceFolder}/lib/src", ...],
6970
"trace": true
7071
}
7172
```
@@ -75,6 +76,7 @@ To start the emulator and begin debugging automatically:
7576
* `args`: Enter whatever arguments your emulator needs to enable DAP server.
7677
* `stopOnEntry`: Set to `true` to halt at program start.
7778
* `cwd`: Working directory.
79+
* `srcDirs`: Optional additional list of paths to lookup for source files
7880
* `trace`: Enables DAP message logging for troubleshooting.
7981

8082
### Attach to a Running Emulator
@@ -142,6 +144,7 @@ for the pack is being received.
142144
List of emulators supporting this variation of DAP:
143145

144146
* Emu <img src="https://raw.githubusercontent.com/X65/emu/main/emu.gif" alt="Emu"> — The [X65 Computer](https://x65.zone/) Emulator.
147+
* Steckschwein <img src="https://www.steckschwein.de/steckschwein32.png" alt="Steckschwein Emulator"> — The [Steckschwein](https://www.steckschwein.de/) Emulator.
145148

146149
If you know any other, please [create a PR][4] with an update to the list.
147150

package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@
178178
"type": "string",
179179
"description": "Absolute path to the working directory.",
180180
"default": "${cwd}"
181+
},
182+
"srcDirs": {
183+
"type": "array",
184+
"items": {
185+
"type": "string"
186+
},
187+
"description": "An additional list of lookup paths for source files - e.g. required if we step from main debug code into a subroutine of a library",
188+
"default": false
181189
}
182190
}
183191
},
@@ -203,6 +211,14 @@
203211
"type": "boolean",
204212
"description": "Run without debugging.",
205213
"default": false
214+
},
215+
"srcDirs": {
216+
"type": "array",
217+
"items": {
218+
"type": "string"
219+
},
220+
"description": "An additional list of lookup paths for source files - e.g. required if we step from main debug code into a subroutine of a library",
221+
"default": false
206222
}
207223
}
208224
}

src/cc65Debug.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
15+
import * as fs from "node:fs";
1516
import * as path from "node:path";
1617
import { Logger, LoggingDebugSession, TerminatedEvent, logger } from "@vscode/debugadapter";
1718
import type { DebugProtocol } from "@vscode/debugprotocol";
@@ -52,6 +53,8 @@ interface IRequestArguments extends DebugProtocol.LaunchRequestArguments {
5253
trace?: boolean;
5354
/** run without debugging */
5455
noDebug?: boolean;
56+
/** An additional list of lookup paths for source files - e.g. required if we step from main debug code into a subroutine of a library */
57+
srcDirs?: string[];
5558
}
5659

5760
interface ILaunchRequestArguments extends IRequestArguments {
@@ -105,6 +108,11 @@ export class Cc65DebugSession extends LoggingDebugSession {
105108
this.setDebuggerLinesStartAt1(true);
106109
this.setDebuggerColumnsStartAt1(true);
107110

111+
const srcDirs: string[] = this._session.configuration.srcDirs || [];
112+
113+
this._debugPathBases = [
114+
...new Set([...this._debugPathBases, ...((srcDirs as string[]) ?? [])]),
115+
];
108116
// make sure to 'Stop' the buffered logging if 'trace' is not set
109117
logger.setup(
110118
this._session.configuration.trace ? Logger.LogLevel.Verbose : Logger.LogLevel.Stop,
@@ -696,10 +704,14 @@ export class Cc65DebugSession extends LoggingDebugSession {
696704
showUser: true,
697705
});
698706
}
699-
707+
const dbgFileBaseName = path.basename(sourceBase);
708+
const dbgFileSize = fs.statSync(source.path).size;
700709
const dbgFile = this._debugData?.file.find((file) => {
701710
const filePath = `${path.posix.sep}${normalizePath(file.name)}`;
702-
return filePath.endsWith(`${path.posix.sep}${sourceBase}`);
711+
return (
712+
dbgFileSize === file.size &&
713+
filePath.endsWith(`${path.posix.sep}${dbgFileBaseName}`)
714+
);
703715
});
704716

705717
if (!response.body) response.body = { breakpoints: [] };
@@ -717,7 +729,7 @@ export class Cc65DebugSession extends LoggingDebugSession {
717729
}
718730

719731
// Store path base for later name reconstruction
720-
const fileBase = normalizePath(dbgFile.name).slice(0, -sourceBase.length);
732+
const fileBase = sourceBase.slice(0, -normalizePath(dbgFile.name).length);
721733
if (!this._debugPathBases.includes(fileBase)) this._debugPathBases.push(fileBase);
722734

723735
// map source lines to memory addresses
@@ -926,9 +938,15 @@ export class Cc65DebugSession extends LoggingDebugSession {
926938
// --------------------------------------------------------------------
927939
private dbgFile2workspace(dbgFile: DbgFile) {
928940
const fileName = normalizePath(dbgFile.name);
929-
for (const base of this._debugPathBases) {
930-
if (fileName.startsWith(base)) {
931-
return fileName.slice(base.length);
941+
// lookup relative to workspaceFolder
942+
const workspaceFolder = normalizePath(
943+
path.resolve(this._session.workspaceFolder?.uri.fsPath || "."),
944+
);
945+
// build path and do fs lookup
946+
for (const pathBase of this._debugPathBases) {
947+
const candidate = path.resolve(workspaceFolder, pathBase, fileName);
948+
if (fs.existsSync(candidate) && fs.statSync(candidate).size === dbgFile.size) {
949+
return normalizePath(path.relative(workspaceFolder, candidate));
932950
}
933951
}
934952
}

0 commit comments

Comments
 (0)