add doc strings

This commit is contained in:
Jason2866
2026-03-11 19:57:06 +01:00
committed by GitHub
parent 3611e7d22a
commit c8f8ed2a9c
8 changed files with 80 additions and 1 deletions
+2 -1
View File
@@ -20,6 +20,7 @@ jobs:
registry-url: https://registry.npmjs.org
- run: npm install -g npm@latest
- run: npm ci
- run: npm install
- run: rm -rf dist
- run: npm run build
- run: npm publish --provenance --access public
+32
View File
@@ -23,6 +23,7 @@ import { MI2 } from './mi2/mi2';
import { MINode } from './mi_parse';
import { SymbolTable } from './symbols';
/** Wraps a variable reference with options. */
class ExtendedVariable {
constructor(
public name: string,
@@ -45,6 +46,7 @@ class CustomContinuedEvent extends Event {
}
}
/** DAP implementation on top of GDB/MI2. */
export class GDBDebugSession extends DebugSession {
private variableHandles = new Handles<string | VariableObject | ExtendedVariable>(131072);
private variableHandlesReverse: { [name: string]: number } = {};
@@ -68,6 +70,7 @@ export class GDBDebugSession extends DebugSession {
super(debuggerLinesStartAt1, isServer);
}
/** Attaches MI2 listeners and sends InitializedEvent. */
initDebugger(): void {
this.miDebugger.on('launcherror', this.launchError.bind(this));
this.miDebugger.on('quit', this.quitEvent.bind(this));
@@ -85,6 +88,7 @@ export class GDBDebugSession extends DebugSession {
this.sendEvent(new InitializedEvent());
}
/** Responds to DAP initialize with capabilities. */
protected initializeRequest(response: any, args: any): void {
response.body.supportsConditionalBreakpoints = true;
response.body.supportsConfigurationDoneRequest = true;
@@ -98,16 +102,19 @@ export class GDBDebugSession extends DebugSession {
this.sendResponse(response);
}
/** Handles DAP launch request. */
protected launchRequest(response: any, args: any): void {
this.args = args;
this.processLaunchAttachRequest(response, false);
}
/** Handles DAP attach request. */
protected attachRequest(response: any, args: any): void {
this.args = args;
this.processLaunchAttachRequest(response, true);
}
/** Core launch/attach handler. */
private processLaunchAttachRequest(response: any, isAttach: boolean): void {
this.quit = false;
this.attached = false;
@@ -168,6 +175,7 @@ export class GDBDebugSession extends DebugSession {
);
}
/** Handles custom DAP requests. */
protected customRequest(command: string, response: any, args: any): void {
switch (command) {
case 'set-force-disassembly':
@@ -238,6 +246,7 @@ export class GDBDebugSession extends DebugSession {
}
}
/** Handles disassemble custom request. */
protected async disassembleRequest(response: any, args: any): Promise<void> {
if (args.function) {
try {
@@ -282,6 +291,7 @@ export class GDBDebugSession extends DebugSession {
}
}
/** Gets/caches function disassembly. */
private async getDisassemblyForFunction(functionName: string, file: string): Promise<any> {
const func = this.symbolTable.getFunctionByName(functionName, file);
if (!func) {
@@ -309,6 +319,7 @@ export class GDBDebugSession extends DebugSession {
return func;
}
/** Gets disassembly for address range. */
private async getDisassemblyForAddresses(startAddress: number, length: number): Promise<any[]> {
const endAddress = startAddress + length;
const result = await this.miDebugger.sendCommand(
@@ -324,6 +335,7 @@ export class GDBDebugSession extends DebugSession {
}));
}
/** Reads memory via MI. */
private customReadMemoryRequest(response: any, address: number, length: number): void {
this.miDebugger.examineMemory(address, length).then(
(data) => {
@@ -342,6 +354,7 @@ export class GDBDebugSession extends DebugSession {
);
}
/** Writes memory via MI. */
private customWriteMemoryRequest(response: any, address: number, data: string): void {
const hexAddr = hexFormat(address, 8);
this.miDebugger.sendCommand(`data-write-memory-bytes ${hexAddr} ${data}`).then(
@@ -355,6 +368,7 @@ export class GDBDebugSession extends DebugSession {
);
}
/** Reads CPU registers via MI. */
private customReadRegistersRequest(response: any): void {
this.miDebugger.sendCommand('data-list-register-values x').then(
(result) => {
@@ -379,6 +393,7 @@ export class GDBDebugSession extends DebugSession {
);
}
/** Reads register names via MI. */
private customReadRegisterListRequest(response: any): void {
this.miDebugger.sendCommand('data-list-register-names').then(
(result) => {
@@ -402,6 +417,7 @@ export class GDBDebugSession extends DebugSession {
);
}
/** Handles DAP disconnect. */
protected disconnectRequest(response: any, args: any): void {
if (this.miDebugger) {
if (this.attached) {
@@ -413,6 +429,7 @@ export class GDBDebugSession extends DebugSession {
this.sendResponse(response);
}
/** Handles DAP terminate. */
protected terminateRequest(response: any, args: any): void {
if (this.miDebugger) {
this.miDebugger.stop();
@@ -420,6 +437,7 @@ export class GDBDebugSession extends DebugSession {
this.sendResponse(response);
}
/** Handles DAP restart. */
protected restartRequest(response: any, args: any): void {
const doRestart = () => {
this.miDebugger
@@ -448,10 +466,12 @@ export class GDBDebugSession extends DebugSession {
}
}
/** Emits adapter output event. */
private handleAdapterOutput(text: string): void {
this.sendEvent(new AdapterOutputEvent(text, 'out'));
}
/** Forwards GDB console/log messages. */
private handleMsg(type: string, message: string): void {
if (type === 'target') {
type = 'stdout';
@@ -462,12 +482,14 @@ export class GDBDebugSession extends DebugSession {
this.sendEvent(new OutputEvent(message, type));
}
/** Emits continued events. */
private handleRunning(info: any): void {
this.stopped = false;
this.sendEvent(new ContinuedEvent(this.currentThreadId, true));
this.sendEvent(new CustomContinuedEvent(this.currentThreadId, true));
}
/** Emits stopped events for breakpoints. */
private handleBreakpoint(info: any): void {
const threadId = parseInt(info.record('thread-id') || this.currentThreadId);
this.stopped = true;
@@ -476,6 +498,7 @@ export class GDBDebugSession extends DebugSession {
this.sendEvent(new CustomStopEvent('breakpoint', threadId));
}
/** Emits stopped events for step end. */
private handleBreak(info: any): void {
this.stopped = true;
this.stoppedReason = 'step';
@@ -483,6 +506,7 @@ export class GDBDebugSession extends DebugSession {
this.sendEvent(new CustomStopEvent('step', this.currentThreadId));
}
/** Emits stopped events for user pause. */
private handlePause(info: any): void {
this.stopped = true;
this.stoppedReason = 'user request';
@@ -490,19 +514,23 @@ export class GDBDebugSession extends DebugSession {
this.sendEvent(new CustomStopEvent('user request', this.currentThreadId));
}
/** Emits thread started. */
private handleThreadCreated(info: any): void {
this.sendEvent(new ThreadEvent('started', info.threadId));
}
/** Emits thread exited. */
private handleThreadExited(info: any): void {
this.sendEvent(new ThreadEvent('exited', info.threadId));
}
/** Emits thread selected. */
private handleThreadSelected(info: any): void {
this.currentThreadId = info.threadId;
this.sendEvent(new ThreadEvent('selected', info.threadId));
}
/** Handles unexpected stop. */
private stopEvent(info: any): void {
if (!this.started) {
this.crashed = true;
@@ -515,16 +543,19 @@ export class GDBDebugSession extends DebugSession {
}
}
/** Handles GDB quit. */
private quitEvent(): void {
this.quit = true;
this.sendEvent(new TerminatedEvent());
}
/** Handles launch error. */
private launchError(err: any): void {
this.handleMsg('stderr', `Could not start debugger process > ${err.toString()}\n`);
this.quitEvent();
}
/** Handles function breakpoints. */
protected setFunctionBreakPointsRequest(response: any, args: any): void {
if (!args.breakpoints || !args.breakpoints.length) {
return;
@@ -579,6 +610,7 @@ export class GDBDebugSession extends DebugSession {
}
}
/** Handles source/disassembly breakpoints. */
protected setBreakPointsRequest(response: any, args: any): void {
const setBreakpoints = async (shouldContinue: boolean) => {
this.debugReady = true;
+2
View File
@@ -16,6 +16,7 @@ export function isExpandable(value: string): number {
return 0;
}
if (value.startsWith('{...}')) {
/** Determines if a value string is expandable. */
return 2;
}
if (value[0] === '{') {
@@ -39,6 +40,7 @@ export function expandValue(
root: string = '',
extra?: any
): any {
/** Parses a GDB value string into a DAP variable tree. */
const parseQuotedString = (): string => {
value = value.trim();
if (value[0] !== '"' && value[0] !== "'") {
+14
View File
@@ -33,6 +33,7 @@ export class MI2 extends EventEmitter {
super();
}
/** Spawns GDB and sends startup MI commands. */
connect(cwd: string, commands: string[]): Promise<boolean> {
return new Promise((resolve, reject) => {
const args = [...this.args];
@@ -67,6 +68,7 @@ export class MI2 extends EventEmitter {
});
}
/** Buffers and dispatches stdout lines. */
stdout(data: any): void {
this.buffer += typeof data === 'string' ? data : data.toString('utf8');
const newlineIndex = this.buffer.lastIndexOf('\n');
@@ -81,6 +83,7 @@ export class MI2 extends EventEmitter {
}
}
/** Buffers and logs stderr lines. */
stderr(data: any): void {
this.errbuf += typeof data === 'string' ? data : data.toString('utf8');
const newlineIndex = this.errbuf.lastIndexOf('\n');
@@ -94,6 +97,7 @@ export class MI2 extends EventEmitter {
}
}
/** Splits and logs multi-line stderr. */
onOutputStderr(output: string): void {
const lines = output.split('\n');
lines.forEach((line) => {
@@ -101,6 +105,7 @@ export class MI2 extends EventEmitter {
});
}
/** Handles partial line; logs non-MI output. */
onOutputPartial(line: string): boolean {
if (isPlainOutput(line)) {
this.logNoNewLine('stdout', line);
@@ -109,6 +114,7 @@ export class MI2 extends EventEmitter {
return false;
}
/** Parses and routes MI output lines. */
onOutput(output: string): void {
const lines = output.split('\n');
lines.forEach((line) => {
@@ -208,6 +214,7 @@ export class MI2 extends EventEmitter {
});
}
/** Sends -gdb-exit; optional force-kill after 1s. */
stop(forceKill: boolean = false): void {
if (forceKill) {
const proc = this.process;
@@ -221,6 +228,7 @@ export class MI2 extends EventEmitter {
this.sendRaw('-gdb-exit');
}
/** Sends -target-detach with fallback kill. */
detach(): void {
const proc = this.process;
const killTimeout = setTimeout(() => {
@@ -232,6 +240,7 @@ export class MI2 extends EventEmitter {
this.sendRaw('-target-detach');
}
/** Interrupts a thread. */
interrupt(threadId: number): Promise<boolean> {
return new Promise((resolve, reject) => {
this.sendCommand(`exec-interrupt --thread ${threadId}`).then(
@@ -243,6 +252,7 @@ export class MI2 extends EventEmitter {
});
}
/** Continues a thread. */
continue(threadId: number): Promise<boolean> {
return new Promise((resolve, reject) => {
this.sendCommand(`exec-continue --thread ${threadId}`).then(
@@ -254,6 +264,7 @@ export class MI2 extends EventEmitter {
});
}
/** Steps to next line/instruction. */
next(threadId: number, instruction: boolean): Promise<boolean> {
return new Promise((resolve, reject) => {
const command = instruction ? 'exec-next-instruction' : 'exec-next';
@@ -266,6 +277,7 @@ export class MI2 extends EventEmitter {
});
}
/** Steps into next line/instruction. */
step(threadId: number, instruction: boolean): Promise<boolean> {
return new Promise((resolve, reject) => {
const command = instruction ? 'exec-step-instruction' : 'exec-step';
@@ -278,6 +290,7 @@ export class MI2 extends EventEmitter {
});
}
/** Steps out of current function. */
stepOut(threadId: number): Promise<boolean> {
return new Promise((resolve, reject) => {
this.sendCommand(`exec-finish --thread ${threadId}`).then(
@@ -289,6 +302,7 @@ export class MI2 extends EventEmitter {
});
}
/** Restarts by sending MI commands. */
restart(commands: string[]): Promise<boolean> {
return this._sendCommandSequence(commands);
}
+4
View File
@@ -31,6 +31,7 @@ export class VariableObject {
applyChanges(node: any): void {
this.value = MINode.valueOf(node, 'value');
if (MINode.valueOf(node, 'type_changed')) {
/** Applies a -var-update changelist entry. */
this.type = MINode.valueOf(node, 'new_type');
}
this.dynamic = !!MINode.valueOf(node, 'dynamic');
@@ -42,6 +43,7 @@ export class VariableObject {
isCompound(): boolean {
return (
this.numchild > 0 ||
/** True if this variable has children. */
this.value === '{...}' ||
(this.dynamic && (this.displayhint === 'array' || this.displayhint === 'map'))
);
@@ -51,6 +53,7 @@ export class VariableObject {
toProtocolVariable(): any {
return {
name: this.exp,
/** Converts to DAP Variable. */
evaluateName: this.fullExp || this.exp,
value: this.value === undefined ? '<unknown>' : this.value,
type: this.type,
@@ -80,6 +83,7 @@ export class MIError {
/** Returns "<message> (from <source>)". */
toString(): string {
return `${(this as any).message} (from ${(this as any).source})`;
/** Returns "<message> (from <source>)". */
}
}
+3
View File
@@ -9,6 +9,9 @@ import { MemoryTreeProvider } from './frontend/memory_tree_provider';
import { PeripheralTreeProvider, RecordType as PeripheralRecordType } from './frontend/peripheral';
import { RegisterTreeProvider, RecordType as RegisterRecordType } from './frontend/registers';
/**
* Main entry point and controller for the PlatformIO Debug VS Code extension.
*/
class PlatformIODebugExtension {
private adapterOutputChannel: vscode.OutputChannel = null;
private functionSymbols: any[] = null;
+5
View File
@@ -23,6 +23,7 @@ export class TreeNode extends vscode.TreeItem {
title: 'Selected Node',
};
}
/** TreeItem for registers panel. */
}
/** Base for register tree nodes. */
@@ -47,6 +48,7 @@ export class BaseNode {
setFormat(format: NumberFormat): void {
this.format = format;
}
/** Base for register tree nodes. */
}
/** CPU register node; may have FieldNode children. */
@@ -85,6 +87,7 @@ export class RegisterNode extends BaseNode {
this.currentValue = 0;
}
/** CPU register node; may have FieldNode children. */
extractBits(offset: number, width: number): number {
return extractBits(this.currentValue, offset, width);
}
@@ -153,6 +156,7 @@ export class RegisterNode extends BaseNode {
}
return settings;
}
/** Named bit-field within special registers. */
}
/** Named bit-field within special registers. */
@@ -217,6 +221,7 @@ export class FieldNode extends BaseNode {
}
return null;
}
/** TreeDataProvider for platformio-debug.registers. */
}
/** TreeDataProvider for platformio-debug.registers. */
+18
View File
@@ -2,6 +2,9 @@
* Formats a number as a zero-padded hexadecimal string.
*/
export function hexFormat(value: number, padding: number = 8, includePrefix: boolean = true): string {
/**
* Formats a number as a zero-padded hexadecimal string.
*/
let result = value.toString(16);
while (result.length < padding) {
result = '0' + result;
@@ -18,6 +21,9 @@ export function binaryFormat(
includePrefix: boolean = true,
groupByNibble: boolean = false
): string {
/**
* Formats a number as a binary string, with optional nibble grouping.
*/
let result = (value >>> 0).toString(2);
while (result.length < padding) {
result = '0' + result;
@@ -40,6 +46,9 @@ export function binaryFormat(
* Creates a bitmask covering the specified bit range.
*/
export function createMask(offset: number, width: number): number {
/**
* Creates a bitmask covering the specified bit range.
*/
let mask = 0;
const end = offset + width - 1;
for (let i = offset; i <= end; i++) {
@@ -52,6 +61,9 @@ export function createMask(offset: number, width: number): number {
* Extracts a bit field from a value.
*/
export function extractBits(value: number, offset: number, width: number): number {
/**
* Extracts a bit field from a value.
*/
return ((value & createMask(offset, width)) >>> offset) >>> 0;
}
@@ -59,6 +71,9 @@ export function extractBits(value: number, offset: number, width: number): numbe
* Parses a URL query string into a key-value map.
*/
export function parseQuery(queryString: string): { [key: string]: string } {
/**
* Parses a URL query string into a key-value map.
*/
const params: { [key: string]: string } = {};
const pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
for (const pair of pairs) {
@@ -72,6 +87,9 @@ export function parseQuery(queryString: string): { [key: string]: string } {
* Encodes a function name and source file into a disassembly:// URI.
*/
export function encodeDisassembly(name: string, file: string): string {
/**
* Encodes a function name and source file into a disassembly:// URI.
*/
let uri = 'disassembly:///';
if (file) {
uri += `${file}:`;