mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-10 02:48:33 +00:00
ATL-730: Refactored the debug extension.
Wired in the `cortex.debug` VSXE. Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
@@ -127,6 +127,7 @@ import { TabBarRenderer } from './theia/core/tab-bars';
|
||||
import { EditorCommandContribution } from './theia/editor/editor-command';
|
||||
import { NavigatorTabBarDecorator as TheiaNavigatorTabBarDecorator } from '@theia/navigator/lib/browser/navigator-tab-bar-decorator';
|
||||
import { NavigatorTabBarDecorator } from './theia/navigator/navigator-tab-bar-decorator';
|
||||
import { Debug } from './contributions/debug';
|
||||
|
||||
const ElementQueries = require('css-element-queries/src/ElementQueries');
|
||||
|
||||
@@ -327,6 +328,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
Contribution.configure(bind, LibraryExamples);
|
||||
Contribution.configure(bind, IncludeLibrary);
|
||||
Contribution.configure(bind, About);
|
||||
Contribution.configure(bind, Debug);
|
||||
|
||||
bind(OutputServiceImpl).toSelf().inSingletonScope().onActivation(({ container }, outputService) => {
|
||||
WebSocketConnectionProvider.createProxy(container, OutputServicePath, outputService);
|
||||
|
||||
134
arduino-ide-extension/src/browser/contributions/debug.ts
Normal file
134
arduino-ide-extension/src/browser/contributions/debug.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { inject, injectable } from 'inversify';
|
||||
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 { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import { URI, Command, CommandRegistry, SketchContribution, TabBarToolbarRegistry } from './contribution';
|
||||
|
||||
@injectable()
|
||||
export class Debug extends SketchContribution {
|
||||
|
||||
@inject(HostedPluginSupport)
|
||||
protected hostedPluginSupport: HostedPluginSupport;
|
||||
|
||||
@inject(NotificationCenter)
|
||||
protected readonly notificationCenter: NotificationCenter;
|
||||
|
||||
@inject(ExecutableService)
|
||||
protected readonly executableService: ExecutableService;
|
||||
|
||||
@inject(BoardsService)
|
||||
protected readonly boardService: BoardsService;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
/**
|
||||
* If `undefined`, debugging is enabled. Otherwise, the reason why it's disabled.
|
||||
*/
|
||||
protected _disabledMessages?: string = 'No board selected'; // Initial pessimism.
|
||||
protected disabledMessageDidChangeEmitter = new Emitter<string | undefined>();
|
||||
protected onDisabledMessageDidChange = this.disabledMessageDidChangeEmitter.event;
|
||||
|
||||
protected get disabledMessage(): string | undefined {
|
||||
return this._disabledMessages;
|
||||
}
|
||||
protected set disabledMessage(message: string | undefined) {
|
||||
this._disabledMessages = message;
|
||||
this.disabledMessageDidChangeEmitter.fire(this._disabledMessages);
|
||||
}
|
||||
|
||||
protected readonly debugToolbarItem = {
|
||||
id: Debug.Commands.START_DEBUGGING.id,
|
||||
command: Debug.Commands.START_DEBUGGING.id,
|
||||
tooltip: `${this.disabledMessage ? `Debug - ${this.disabledMessage}` : 'Start Debugging'}`,
|
||||
priority: 3,
|
||||
onDidChange: this.onDisabledMessageDidChange as Event<void>
|
||||
};
|
||||
|
||||
onStart(): void {
|
||||
this.onDisabledMessageDidChange(() => this.debugToolbarItem.tooltip = `${this.disabledMessage ? `Debug - ${this.disabledMessage}` : 'Start Debugging'}`);
|
||||
const refreshState = async (board: Board | undefined = this.boardsServiceProvider.boardsConfig.selectedBoard) => {
|
||||
if (!board) {
|
||||
this.disabledMessage = 'No board selected';
|
||||
return;
|
||||
}
|
||||
const fqbn = board.fqbn;
|
||||
if (!fqbn) {
|
||||
this.disabledMessage = `Platform is not installed for '${board.name}'`;
|
||||
return;
|
||||
}
|
||||
const details = await this.boardService.getBoardDetails({ fqbn });
|
||||
if (!details) {
|
||||
this.disabledMessage = `Platform is not installed for '${board.name}'`;
|
||||
return;
|
||||
}
|
||||
const { debuggingSupported } = details;
|
||||
if (!debuggingSupported) {
|
||||
this.disabledMessage = `Debugging is not supported by '${board.name}'`;
|
||||
} else {
|
||||
this.disabledMessage = undefined;
|
||||
}
|
||||
}
|
||||
this.boardsServiceProvider.onBoardsConfigChanged(({ selectedBoard }) => refreshState(selectedBoard));
|
||||
this.notificationCenter.onPlatformInstalled(() => refreshState());
|
||||
this.notificationCenter.onPlatformUninstalled(() => refreshState());
|
||||
refreshState();
|
||||
}
|
||||
|
||||
registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(Debug.Commands.START_DEBUGGING, {
|
||||
execute: () => this.startDebug(),
|
||||
isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left',
|
||||
isEnabled: () => !this.disabledMessage
|
||||
});
|
||||
}
|
||||
|
||||
registerToolbarItems(registry: TabBarToolbarRegistry): void {
|
||||
registry.registerItem(this.debugToolbarItem);
|
||||
}
|
||||
|
||||
protected async startDebug(board: Board | undefined = this.boardsServiceProvider.boardsConfig.selectedBoard): Promise<void> {
|
||||
if (!board) {
|
||||
return;
|
||||
}
|
||||
const { name, fqbn } = board;
|
||||
if (!fqbn) {
|
||||
return;
|
||||
}
|
||||
await this.hostedPluginSupport.didStart;
|
||||
const [sketch, executables] = await Promise.all([
|
||||
this.sketchServiceClient.currentSketch(),
|
||||
this.executableService.list()
|
||||
]);
|
||||
if (!sketch) {
|
||||
return;
|
||||
}
|
||||
const [cliPath, sketchPath] = await Promise.all([
|
||||
this.fileService.fsPath(new URI(executables.cliUri)),
|
||||
this.fileService.fsPath(new URI(sketch.uri))
|
||||
])
|
||||
const config = {
|
||||
cliPath,
|
||||
board: {
|
||||
fqbn,
|
||||
name
|
||||
},
|
||||
sketchPath
|
||||
};
|
||||
return this.commandService.executeCommand('arduino.debug.start', config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace Debug {
|
||||
export namespace Commands {
|
||||
export const START_DEBUGGING: Command = {
|
||||
id: 'arduino-start-debug',
|
||||
label: 'Start Debugging',
|
||||
category: 'Arduino'
|
||||
}
|
||||
}
|
||||
}
|
||||
4
arduino-ide-extension/src/browser/icons/debug-dark.svg
Normal file
4
arduino-ide-extension/src/browser/icons/debug-dark.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<!--Copyright (c) Microsoft Corporation. All rights reserved.-->
|
||||
<!--Copyright (C) 2019 TypeFox and others.-->
|
||||
<!--Licensed under the MIT License. See License.txt in the project root for license information.-->
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="#F6F6F6" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0)"><path d="M15.1673 18.0687V23.0247C15.1673 23.5637 15.2723 24.5 14.7315 24.5H12.8328V23.3327H14V19.6122L13.7988 19.4022C13.0604 20.0803 12.1008 20.4669 11.0986 20.49C10.0964 20.5132 9.11994 20.1714 8.351 19.5282C7 18.1737 7.13826 16.3327 8.60475 14H4.66726V15.1672H3.50001V13.2685C3.50001 12.7277 4.43626 12.8327 4.97526 12.8327H9.76326L15.1673 18.0687ZM11.6673 5.83275H10.5V4.66725H12.775C13.3123 4.66725 14 4.9245 14 5.4635V9.366L14.8593 10.3862C14.927 9.83979 15.1906 9.33644 15.6013 8.96958C16.0119 8.60271 16.5416 8.39723 17.0923 8.39125C17.2298 8.37945 17.3684 8.39492 17.5 8.43675V5.83275H18.6673V8.88825C18.703 8.99154 18.7618 9.08536 18.8391 9.16265C18.9164 9.23995 19.0102 9.29871 19.1135 9.3345H22.1673V10.5H19.5615C19.593 10.5 19.6105 10.675 19.6105 10.85C19.6058 11.4034 19.4011 11.9365 19.0341 12.3508C18.6671 12.7651 18.1626 13.0326 17.6138 13.104L18.634 14H22.5383C23.0773 14 23.3345 14.6807 23.3345 15.225V17.5H22.1673V16.3327H19.2273L11.6673 8.98275V5.83275ZM14 0C11.2311 0 8.52431 0.821086 6.22202 2.35943C3.91973 3.89776 2.12532 6.08426 1.06569 8.64243C0.00606593 11.2006 -0.271181 14.0155 0.269012 16.7313C0.809205 19.447 2.14258 21.9416 4.10051 23.8995C6.05845 25.8574 8.55301 27.1908 11.2687 27.731C13.9845 28.2712 16.7994 27.9939 19.3576 26.9343C21.9157 25.8747 24.1022 24.0803 25.6406 21.778C27.1789 19.4757 28 16.7689 28 14C28 10.287 26.525 6.72601 23.8995 4.1005C21.274 1.475 17.713 0 14 0V0ZM25.6673 14C25.6692 16.6908 24.7364 19.2988 23.0283 21.378L6.622 4.97175C8.33036 3.57269 10.4009 2.68755 12.5927 2.41935C14.7845 2.15115 17.0074 2.51091 19.0027 3.45676C20.998 4.40262 22.6836 5.89567 23.8635 7.76217C25.0433 9.62867 25.6689 11.7919 25.6673 14ZM2.33276 14C2.33066 11.3091 3.26351 8.70111 4.97176 6.622L21.378 23.03C19.6693 24.4284 17.5987 25.313 15.407 25.5807C13.2153 25.8485 10.9926 25.4884 8.99754 24.5425C7.00244 23.5965 5.31693 22.1036 4.13708 20.2373C2.95722 18.3709 2.33152 16.208 2.33276 14Z" fill="white"/></g><defs><clipPath id="clip0"><rect width="28" height="28" fill="#F6F6F6"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -64,6 +64,23 @@
|
||||
mask-position: 28px -4px;
|
||||
}
|
||||
|
||||
.arduino-start-debug-icon {
|
||||
-webkit-mask: url('../icons/debug-dark.svg') 50%;
|
||||
mask: url('../icons/debug-dark.svg') 50%;
|
||||
-webkit-mask-size: 100%;
|
||||
mask-size: 100%;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--theia-ui-button-font-color);
|
||||
}
|
||||
|
||||
.arduino-start-debug {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
#arduino-toolbar-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
@@ -68,6 +68,9 @@ export class ApplicationShell extends TheiaApplicationShell {
|
||||
}
|
||||
|
||||
async saveAll(): Promise<void> {
|
||||
if (!this.canSaveAll()) { // This is a quick fix for not saving the editor when there are no dirty editors.
|
||||
return; // https://github.com/bcmi-labs/arduino-editor/pull/172#issuecomment-741831888
|
||||
}
|
||||
if (this.connectionStatusService.currentStatus === ConnectionStatus.OFFLINE) {
|
||||
this.messageService.error('Could not save the sketch. Please copy your unsaved work into your favorite text editor, and restart the IDE.');
|
||||
return; // Theia does not reject on failed save: https://github.com/eclipse-theia/theia/pull/8803
|
||||
|
||||
@@ -99,7 +99,7 @@ export interface BoardsService extends Installable<BoardsPackage>, Searchable<Bo
|
||||
*/
|
||||
getAvailablePorts(): Promise<Port[]>;
|
||||
getState(): Promise<AvailablePorts>;
|
||||
getBoardDetails(options: { fqbn: string }): Promise<BoardDetails>;
|
||||
getBoardDetails(options: { fqbn: string }): Promise<BoardDetails | undefined>;
|
||||
getBoardPackage(options: { id: string }): Promise<BoardsPackage | undefined>;
|
||||
getContainerBoardPackage(options: { fqbn: string }): Promise<BoardsPackage | undefined>;
|
||||
// The CLI cannot do fuzzy search. This method provides all boards and we do the fuzzy search (with monaco) on the frontend.
|
||||
@@ -272,6 +272,7 @@ export interface BoardDetails {
|
||||
readonly requiredTools: Tool[];
|
||||
readonly configOptions: ConfigOption[];
|
||||
readonly programmers: Programmer[];
|
||||
readonly debuggingSupported: boolean;
|
||||
}
|
||||
|
||||
export interface Tool {
|
||||
|
||||
@@ -67,7 +67,7 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
return coreClient;
|
||||
}
|
||||
|
||||
async getBoardDetails(options: { fqbn: string }): Promise<BoardDetails> {
|
||||
async getBoardDetails(options: { fqbn: string }): Promise<BoardDetails | undefined> {
|
||||
const coreClient = await this.coreClient();
|
||||
const { client, instance } = coreClient;
|
||||
const { fqbn } = options;
|
||||
@@ -77,7 +77,9 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
const detailsResp = await new Promise<BoardDetailsResp | undefined>((resolve, reject) => client.boardDetails(detailsReq, (err, resp) => {
|
||||
if (err) {
|
||||
// Required cores are not installed manually: https://github.com/arduino/arduino-cli/issues/954
|
||||
if (err.message.indexOf('missing platform release') !== -1 && err.message.indexOf('referenced by board') !== -1) {
|
||||
if ((err.message.indexOf('missing platform release') !== -1 && err.message.indexOf('referenced by board') !== -1)
|
||||
// Platform is not installed.
|
||||
|| err.message.indexOf('platform') !== -1 && err.message.indexOf('not installed') !== -1) {
|
||||
resolve(undefined);
|
||||
return;
|
||||
}
|
||||
@@ -88,14 +90,11 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
}));
|
||||
|
||||
if (!detailsResp) {
|
||||
return {
|
||||
fqbn,
|
||||
configOptions: [],
|
||||
programmers: [],
|
||||
requiredTools: []
|
||||
};
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const debuggingSupported = detailsResp.getDebuggingSupported();
|
||||
|
||||
const requiredTools = detailsResp.getToolsdependenciesList().map(t => <Tool>{
|
||||
name: t.getName(),
|
||||
packager: t.getPackager(),
|
||||
@@ -133,7 +132,8 @@ export class BoardsServiceImpl implements BoardsService {
|
||||
fqbn,
|
||||
requiredTools,
|
||||
configOptions,
|
||||
programmers
|
||||
programmers,
|
||||
debuggingSupported
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user