mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-14 14:56:33 +00:00
Improved error reporting on launch
This commit is contained in:
parent
38ab95973e
commit
1441b685ee
@ -1,23 +1,12 @@
|
|||||||
import { injectable, inject } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import { DebugAdapterContribution, DebugAdapterExecutable, DebugAdapterSessionFactory } from '@theia/debug/lib/common/debug-model';
|
import { DebugAdapterContribution, DebugAdapterExecutable, DebugAdapterSessionFactory } from '@theia/debug/lib/common/debug-model';
|
||||||
import { DebugConfiguration } from "@theia/debug/lib/common/debug-configuration";
|
import { DebugConfiguration } from "@theia/debug/lib/common/debug-configuration";
|
||||||
import { MaybePromise } from "@theia/core/lib/common/types";
|
import { MaybePromise } from "@theia/core/lib/common/types";
|
||||||
import { IJSONSchema, IJSONSchemaSnippet } from "@theia/core/lib/common/json-schema";
|
import { IJSONSchema, IJSONSchemaSnippet } from "@theia/core/lib/common/json-schema";
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { BoardsService } from 'arduino-ide-extension/lib/common/protocol/boards-service';
|
|
||||||
import { CoreService } from 'arduino-ide-extension/lib/common/protocol/core-service';
|
|
||||||
import { FileSystem } from '@theia/filesystem/lib/common';
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ArduinoDebugAdapterContribution implements DebugAdapterContribution {
|
export class ArduinoDebugAdapterContribution implements DebugAdapterContribution {
|
||||||
@inject(BoardsService)
|
|
||||||
protected readonly boardsService: BoardsService;
|
|
||||||
|
|
||||||
@inject(CoreService)
|
|
||||||
protected readonly coreService: CoreService;
|
|
||||||
|
|
||||||
@inject(FileSystem)
|
|
||||||
protected readonly fileSystem: FileSystem;
|
|
||||||
|
|
||||||
type = "arduino";
|
type = "arduino";
|
||||||
|
|
||||||
@ -39,26 +28,25 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
|
|||||||
"description": "path to the sketch root ino file",
|
"description": "path to the sketch root ino file",
|
||||||
"default": "${file}",
|
"default": "${file}",
|
||||||
},
|
},
|
||||||
"runToMain": {
|
|
||||||
"description": "If enabled the debugger will run until the start of the main function.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"fqbn": {
|
"fqbn": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Fully-qualified board name to debug on",
|
"description": "Fully-qualified board name to debug on",
|
||||||
"default": ""
|
"default": ""
|
||||||
},
|
},
|
||||||
|
"runToMain": {
|
||||||
|
"description": "If enabled the debugger will run until the start of the main function.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"verbose": {
|
"verbose": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Produce verbose log output",
|
"description": "Produce verbose log output",
|
||||||
"default": "false"
|
"default": false
|
||||||
},
|
},
|
||||||
"debugDebugAdapter": {
|
"debugDebugAdapter": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Start the debug adapter in debug mode (with --inspect-brk)",
|
"description": "Start the debug adapter in debug mode (with --inspect-brk)",
|
||||||
"default": "false"
|
"default": false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +62,7 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
|
|||||||
if (!!config.debugDebugAdapter) {
|
if (!!config.debugDebugAdapter) {
|
||||||
args.push('--inspect-brk')
|
args.push('--inspect-brk')
|
||||||
}
|
}
|
||||||
args = args.concat([path.join(__dirname, 'debug-adapter', 'index.js')]);
|
args = args.concat([path.join(__dirname, 'debug-adapter', 'main')]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
command: "node",
|
command: "node",
|
||||||
@ -88,11 +76,7 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
|
|||||||
name: this.label,
|
name: this.label,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
request: "launch",
|
request: "launch",
|
||||||
|
|
||||||
sketch: "${file}",
|
sketch: "${file}",
|
||||||
|
|
||||||
verbose: true,
|
|
||||||
runToMain: true,
|
|
||||||
},
|
},
|
||||||
<DebugConfiguration>{
|
<DebugConfiguration>{
|
||||||
name: this.label + " (explicit)",
|
name: this.label + " (explicit)",
|
||||||
@ -105,8 +89,8 @@ export class ArduinoDebugAdapterContribution implements DebugAdapterContribution
|
|||||||
gdbServer: "${boardTools:openocd}",
|
gdbServer: "${boardTools:openocd}",
|
||||||
gdbServerArguments: ["-s", "${boardTools:openocd-scripts}", "--file", "${board:openocd-debug-file}"],
|
gdbServerArguments: ["-s", "${boardTools:openocd-scripts}", "--file", "${board:openocd-debug-file}"],
|
||||||
|
|
||||||
verbose: true,
|
runToMain: false,
|
||||||
runToMain: true,
|
verbose: false,
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
import { normalize } from 'path';
|
import { normalize } from 'path';
|
||||||
import { DebugProtocol } from 'vscode-debugprotocol';
|
import { DebugProtocol } from 'vscode-debugprotocol';
|
||||||
import { Logger, logger, InitializedEvent, OutputEvent, Scope, TerminatedEvent } from 'vscode-debugadapter';
|
import { Logger, logger, InitializedEvent, OutputEvent, Scope, TerminatedEvent, ErrorDestination } from 'vscode-debugadapter';
|
||||||
import { GDBDebugSession, RequestArguments, FrameVariableReference, FrameReference } from 'cdt-gdb-adapter/dist/GDBDebugSession';
|
import { GDBDebugSession, RequestArguments, FrameVariableReference, FrameReference } from 'cdt-gdb-adapter/dist/GDBDebugSession';
|
||||||
import { GDBBackend } from 'cdt-gdb-adapter/dist/GDBBackend';
|
import { GDBBackend } from 'cdt-gdb-adapter/dist/GDBBackend';
|
||||||
import { CmsisBackend } from './cmsis-backend';
|
import { CmsisBackend } from './cmsis-backend';
|
||||||
@ -117,7 +117,6 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
|
|
||||||
protected async setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): Promise<void> {
|
protected async setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): Promise<void> {
|
||||||
await super.setBreakPointsRequest(response, args);
|
await super.setBreakPointsRequest(response, args);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
|
protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
|
||||||
@ -224,13 +223,10 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
this.gdb.on('notifyAsync', (resultClass, resultData) => this.handleGDBNotify(resultClass, resultData));
|
this.gdb.on('notifyAsync', (resultClass, resultData) => this.handleGDBNotify(resultClass, resultData));
|
||||||
|
|
||||||
// gdb server has main info channel on stderr
|
// gdb server has main info channel on stderr
|
||||||
this.gdbServer.on('stderr', data => {
|
this.gdbServer.on('stderr', data => this.sendEvent(new OutputEvent(data, 'stdout')));
|
||||||
this.sendEvent(new OutputEvent(data, 'stdout'))
|
const gdbServerErrors: any[] = []
|
||||||
});
|
const gdbServerErrorAccumulator = (message: any) => gdbServerErrors.push(message);
|
||||||
this.gdbServer.on('error', message => {
|
this.gdbServer.on('error', gdbServerErrorAccumulator);
|
||||||
this.sendEvent(new TerminatedEvent());
|
|
||||||
throw message;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.symbolTable = new SymbolTable(args.program, args.objdump);
|
this.symbolTable = new SymbolTable(args.program, args.objdump);
|
||||||
@ -264,12 +260,18 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
this.sendEvent(new OutputEvent(`Starting debugger: ${JSON.stringify(args)}`));
|
this.sendEvent(new OutputEvent(`Starting debugger: ${JSON.stringify(args)}`));
|
||||||
await this.gdbServer.spawn(args);
|
await this.gdbServer.spawn(args);
|
||||||
await this.spawn(args);
|
await this.spawn(args);
|
||||||
|
if (gdbServerErrors.length > 0) {
|
||||||
|
throw new Error(gdbServerErrors.join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
// Send commands
|
// Send commands
|
||||||
await mi.sendTargetAsyncOn(this.gdb);
|
await mi.sendTargetAsyncOn(this.gdb);
|
||||||
await mi.sendTargetSelectRemote(this.gdb, remote);
|
await mi.sendTargetSelectRemote(this.gdb, remote);
|
||||||
await mi.sendMonitorResetHalt(this.gdb);
|
await mi.sendMonitorResetHalt(this.gdb);
|
||||||
this.sendEvent(new OutputEvent(`Attached to debugger on port ${port}`));
|
this.sendEvent(new OutputEvent(`Attached to debugger on port ${port}`));
|
||||||
|
if (gdbServerErrors.length > 0) {
|
||||||
|
throw new Error(gdbServerErrors.join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
// Download image
|
// Download image
|
||||||
const progressListener = (percent: number) => this.progressEvent(percent, 'Loading Image');
|
const progressListener = (percent: number) => this.progressEvent(percent, 'Loading Image');
|
||||||
@ -287,8 +289,17 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
await mi.sendBreakOnFunction(this.gdb);
|
await mi.sendBreakOnFunction(this.gdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gdbServerErrors.length > 0) {
|
||||||
|
throw new Error(gdbServerErrors.join('\n'));
|
||||||
|
}
|
||||||
this.sendEvent(new OutputEvent(`Image loaded: ${args.program}`));
|
this.sendEvent(new OutputEvent(`Image loaded: ${args.program}`));
|
||||||
this.sendEvent(new InitializedEvent());
|
this.sendEvent(new InitializedEvent());
|
||||||
|
|
||||||
|
this.gdbServer.removeListener('error', gdbServerErrorAccumulator);
|
||||||
|
this.gdbServer.on('error', message => {
|
||||||
|
logger.error(JSON.stringify(message));
|
||||||
|
this.sendEvent(new TerminatedEvent());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getGlobalVariables(frameHandle: number): Promise<DebugProtocol.Variable[]> {
|
private async getGlobalVariables(frameHandle: number): Promise<DebugProtocol.Variable[]> {
|
||||||
@ -378,6 +389,15 @@ export class CmsisDebugSession extends GDBDebugSession {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected sendErrorResponse(response: DebugProtocol.Response,
|
||||||
|
codeOrMessage: number | DebugProtocol.Message, format?: string,
|
||||||
|
variables?: any, dest?: ErrorDestination): void {
|
||||||
|
if (!!format && (dest === undefined || dest === ErrorDestination.User)) {
|
||||||
|
format = format.replace('\n', '<br>');
|
||||||
|
}
|
||||||
|
super.sendErrorResponse(response, codeOrMessage, format, variables, dest);
|
||||||
|
}
|
||||||
|
|
||||||
protected async stopSession() {
|
protected async stopSession() {
|
||||||
// Pause debugging
|
// Pause debugging
|
||||||
if (this.isRunning) {
|
if (this.isRunning) {
|
||||||
|
@ -6,7 +6,7 @@ import * as path from 'path';
|
|||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
|
||||||
const LAUNCH_REGEX = /GDB server started/;
|
const LAUNCH_REGEX = /GDB server started/;
|
||||||
const ERROR_REGEX = /:ERROR:gdbserver:/;
|
const ERROR_REGEX = /^error:/mi;
|
||||||
const PERCENT_MULTIPLIER = 100 / 40; // pyOCD outputs 40 markers for progress
|
const PERCENT_MULTIPLIER = 100 / 40; // pyOCD outputs 40 markers for progress
|
||||||
|
|
||||||
export class OpenocdServer extends AbstractServer {
|
export class OpenocdServer extends AbstractServer {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user