Skip to content

Commit

Permalink
feat: handle when starting debug session failed
Browse files Browse the repository at this point in the history
If the sketch has not been verified, IDE2 offers user a verify action.

Closes #808

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
  • Loading branch information
Akos Kitta committed Jan 11, 2023
1 parent 197cea2 commit 2095e72
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 14 deletions.
53 changes: 45 additions & 8 deletions arduino-ide-extension/src/browser/contributions/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { Event, Emitter } from '@theia/core/lib/common/event';
import { HostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
import { NotificationCenter } from '../notification-center';
import { Board, BoardsService, ExecutableService } from '../../common/protocol';
import {
Board,
BoardsService,
ExecutableService,
Sketch,
} from '../../common/protocol';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
import {
URI,
Expand All @@ -16,9 +21,8 @@ import { MaybePromise, MenuModelRegistry, nls } from '@theia/core/lib/common';
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
import { ArduinoMenus } from '../menu/arduino-menus';

import { MainMenuManager } from '../../common/main-menu-manager';

const COMPILE_FOR_DEBUG_KEY = 'arduino-compile-for-debug';

@injectable()
export class Debug extends SketchContribution {
@inject(HostedPluginSupport)
Expand All @@ -36,9 +40,6 @@ export class Debug extends SketchContribution {
@inject(BoardsServiceProvider)
private readonly boardsServiceProvider: BoardsServiceProvider;

@inject(MainMenuManager)
private readonly mainMenuManager: MainMenuManager;

/**
* If `undefined`, debugging is enabled. Otherwise, the reason why it's disabled.
*/
Expand Down Expand Up @@ -203,7 +204,28 @@ export class Debug extends SketchContribution {
sketchPath,
configPath,
};
return this.commandService.executeCommand('arduino.debug.start', config);
try {
await this.commandService.executeCommand('arduino.debug.start', config);
} catch (err) {
if (await this.isSketchNotVerifiedError(err, sketch)) {
const yes = nls.localize('vscode/extensionsUtils/yes', 'Yes');
const answer = await this.messageService.error(
nls.localize(
'arduino/debug/sketchIsNotCompiled',
"Sketch '{0}' must be verified before starting a debug session. Please verify the sketch and start debugging again. Do you want to verify the sketch now?",
sketch.name
),
yes
);
if (answer === yes) {
this.commandService.executeCommand('arduino-verify-sketch');
}
} else {
this.messageService.error(
err instanceof Error ? err.message : String(err)
);
}
}
}

get compileForDebug(): boolean {
Expand All @@ -215,7 +237,22 @@ export class Debug extends SketchContribution {
const oldState = this.compileForDebug;
const newState = !oldState;
window.localStorage.setItem(COMPILE_FOR_DEBUG_KEY, String(newState));
this.mainMenuManager.update();
this.menuManager.update();
}

private async isSketchNotVerifiedError(
err: unknown,
sketch: Sketch
): Promise<boolean> {
if (err instanceof Error) {
try {
const tempBuildPath = await this.sketchService.tempBuildPath(sketch);
return err.message.includes(tempBuildPath);
} catch {
return false;
}
}
return false;
}
}
export namespace Debug {
Expand Down
6 changes: 6 additions & 0 deletions arduino-ide-extension/src/common/protocol/sketches-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ export interface SketchesService {
* Recursively deletes the sketch folder with all its content.
*/
deleteSketch(sketch: Sketch): Promise<void>;

/**
* This is the JS/TS re-implementation of [`GenBuildPath`](https://github.com/arduino/arduino-cli/blob/c0d4e4407d80aabad81142693513b3306759cfa6/arduino/sketch/sketch.go#L296-L306) of the CLI.
* Pass in a sketch and get the build temporary folder filesystem path calculated from the main sketch file location. This method does not check the existence of the sketch.
*/
tempBuildPath(sketch: Sketch): Promise<string>;
}

export interface SketchRef {
Expand Down
4 changes: 2 additions & 2 deletions arduino-ide-extension/src/node/is-temp-sketch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export const TempSketchPrefix = '.arduinoIDE-unsaved';
@injectable()
export class IsTempSketch {
// If on macOS, the `temp-dir` lib will make sure there is resolved realpath.
// If on Windows, the `C:\Users\KITTAA~1\AppData\Local\Temp` path will be resolved and normalized to `C:\Users\kittaakos\AppData\Local\Temp`.
// If on Windows, the `C:\Users\KITTAA~1\AppData\Local\Temp` path will be resolved and normalized to `c:\Users\kittaakos\AppData\Local\Temp`.
// Note: VS Code URI normalizes the drive letter. `C:` will be converted into `c:`.
// https://github.com/Microsoft/vscode/issues/68325#issuecomment-462239992
private readonly tempDirRealpath = isOSX
readonly tempDirRealpath = isOSX
? tempDir
: maybeNormalizeDrive(fs.realpathSync.native(tempDir));

Expand Down
17 changes: 15 additions & 2 deletions arduino-ide-extension/src/node/sketches-service-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -658,11 +658,24 @@ export class SketchesServiceImpl
return FileUri.create(genBuildPath).toString();
}

async getIdeTempFolderPath(sketch: Sketch): Promise<string> {
private async getIdeTempFolderPath(sketch: Sketch): Promise<string> {
const sketchPath = FileUri.fsPath(sketch.uri);
await fs.readdir(sketchPath); // Validates the sketch folder and rejects if not accessible.
const suffix = crypto.createHash('md5').update(sketchPath).digest('hex');
return path.join(os.tmpdir(), `arduino-ide2-${suffix}`);
return path.join(
this.isTempSketch.tempDirRealpath,
`arduino-ide2-${suffix}`
);
}

async tempBuildPath(sketch: Sketch): Promise<string> {
const sketchPath = FileUri.fsPath(sketch.uri);
const hash = crypto
.createHash('md5')
.update(sketchPath)
.digest('hex')
.toUpperCase();
return join(this.isTempSketch.tempDirRealpath, `arduino-sketch-${hash}`);
}

async deleteSketch(sketch: Sketch): Promise<void> {
Expand Down
3 changes: 2 additions & 1 deletion i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@
"debugWithMessage": "Debug - {0}",
"debuggingNotSupported": "Debugging is not supported by '{0}'",
"noPlatformInstalledFor": "Platform is not installed for '{0}'",
"optimizeForDebugging": "Optimize for Debugging"
"optimizeForDebugging": "Optimize for Debugging",
"sketchIsNotCompiled": "Sketch '{0}' must be verified before starting a debug session. Please verify the sketch and start debugging again. Do you want to verify the sketch now?"
},
"dialog": {
"dontAskAgain": "Don't ask again"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"theiaPluginsDir": "plugins",
"theiaPlugins": {
"vscode-builtin-cpp": "https://open-vsx.org/api/vscode/cpp/1.52.1/file/vscode.cpp-1.52.1.vsix",
"vscode-arduino-tools": "https://downloads.arduino.cc/vscode-arduino-tools/vscode-arduino-tools-0.0.2-beta.5.vsix",
"vscode-arduino-tools": "https://downloads.arduino.cc/vscode-arduino-tools/vscode-arduino-tools-0.0.2-beta.7.vsix",
"vscode-builtin-json": "https://open-vsx.org/api/vscode/json/1.46.1/file/vscode.json-1.46.1.vsix",
"vscode-builtin-json-language-features": "https://open-vsx.org/api/vscode/json-language-features/1.46.1/file/vscode.json-language-features-1.46.1.vsix",
"cortex-debug": "https://downloads.arduino.cc/marus25.cortex-debug/marus25.cortex-debug-1.5.1.vsix",
Expand Down

0 comments on commit 2095e72

Please sign in to comment.