mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-12 11:49:27 +00:00
Show 'progress' indicator during verify/upload.
Closes #575 Closes #1175 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
@@ -4,11 +4,8 @@ import URI from '@theia/core/lib/common/uri';
|
||||
import { ConfirmDialog } from '@theia/core/lib/browser/dialogs';
|
||||
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import {
|
||||
Installable,
|
||||
LibraryService,
|
||||
ResponseServiceClient,
|
||||
} from '../../common/protocol';
|
||||
import { LibraryService, ResponseServiceClient } from '../../common/protocol';
|
||||
import { ExecuteWithProgress } from '../../common/protocol/progressible';
|
||||
import {
|
||||
SketchContribution,
|
||||
Command,
|
||||
@@ -88,7 +85,7 @@ export class AddZipLibrary extends SketchContribution {
|
||||
|
||||
private async doInstall(zipUri: string, overwrite?: boolean): Promise<void> {
|
||||
try {
|
||||
await Installable.doWithProgress({
|
||||
await ExecuteWithProgress.doWithProgress({
|
||||
messageService: this.messageService,
|
||||
progressText:
|
||||
nls.localize('arduino/common/processing', 'Processing') +
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { CoreService } from '../../common/protocol';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import {
|
||||
CoreServiceContribution,
|
||||
Command,
|
||||
CommandRegistry,
|
||||
CoreServiceContribution,
|
||||
MenuModelRegistry,
|
||||
} from './contribution';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
|
||||
@injectable()
|
||||
export class BurnBootloader extends CoreServiceContribution {
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(BurnBootloader.Commands.BURN_BOOTLOADER, {
|
||||
execute: () => this.burnBootloader(),
|
||||
@@ -35,32 +28,19 @@ export class BurnBootloader extends CoreServiceContribution {
|
||||
});
|
||||
}
|
||||
|
||||
async burnBootloader(): Promise<void> {
|
||||
private async burnBootloader(): Promise<void> {
|
||||
const options = await this.options();
|
||||
try {
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const port = boardsConfig.selectedPort;
|
||||
const [fqbn, { selectedProgrammer: programmer }, verify, verbose] =
|
||||
await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
]);
|
||||
|
||||
const board = {
|
||||
...boardsConfig.selectedBoard,
|
||||
name: boardsConfig.selectedBoard?.name || '',
|
||||
fqbn,
|
||||
};
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
await this.coreService.burnBootloader({
|
||||
board,
|
||||
programmer,
|
||||
port,
|
||||
verify,
|
||||
verbose,
|
||||
await this.doWithProgress({
|
||||
progressText: nls.localize(
|
||||
'arduino/bootloader/burningBootloader',
|
||||
'Burning bootloader...'
|
||||
),
|
||||
task: (progressId, coreService) =>
|
||||
coreService.burnBootloader({
|
||||
...options,
|
||||
progressId,
|
||||
}),
|
||||
});
|
||||
this.messageService.info(
|
||||
nls.localize(
|
||||
@@ -75,6 +55,27 @@ export class BurnBootloader extends CoreServiceContribution {
|
||||
this.handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async options(): Promise<CoreService.Options.Bootloader> {
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const port = boardsConfig.selectedPort;
|
||||
const [fqbn, { selectedProgrammer: programmer }, verify, verbose] =
|
||||
await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
]);
|
||||
return {
|
||||
fqbn,
|
||||
programmer,
|
||||
port,
|
||||
verify,
|
||||
verbose,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace BurnBootloader {
|
||||
|
||||
@@ -49,13 +49,16 @@ import {
|
||||
Sketch,
|
||||
CoreService,
|
||||
CoreError,
|
||||
ResponseServiceClient,
|
||||
} from '../../common/protocol';
|
||||
import { ArduinoPreferences } from '../arduino-preferences';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { CoreErrorHandler } from './core-error-handler';
|
||||
import { nls } from '@theia/core';
|
||||
import { OutputChannelManager } from '../theia/output/output-channel';
|
||||
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
|
||||
import { ExecuteWithProgress } from '../../common/protocol/progressible';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
|
||||
export {
|
||||
Command,
|
||||
@@ -167,18 +170,23 @@ export abstract class SketchContribution extends Contribution {
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class CoreServiceContribution extends SketchContribution {
|
||||
@inject(CoreService)
|
||||
protected readonly coreService: CoreService;
|
||||
export abstract class CoreServiceContribution extends SketchContribution {
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
|
||||
@inject(CoreErrorHandler)
|
||||
protected readonly coreErrorHandler: CoreErrorHandler;
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceProvider: BoardsServiceProvider;
|
||||
|
||||
@inject(CoreService)
|
||||
private readonly coreService: CoreService;
|
||||
|
||||
@inject(ClipboardService)
|
||||
private readonly clipboardService: ClipboardService;
|
||||
|
||||
@inject(ResponseServiceClient)
|
||||
private readonly responseService: ResponseServiceClient;
|
||||
|
||||
protected handleError(error: unknown): void {
|
||||
this.coreErrorHandler.tryHandle(error);
|
||||
this.tryToastErrorMessage(error);
|
||||
}
|
||||
|
||||
@@ -214,6 +222,25 @@ export class CoreServiceContribution extends SketchContribution {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
protected async doWithProgress<T>(options: {
|
||||
progressText: string;
|
||||
keepOutput?: boolean;
|
||||
task: (progressId: string, coreService: CoreService) => Promise<T>;
|
||||
}): Promise<T> {
|
||||
const { progressText, keepOutput, task } = options;
|
||||
this.outputChannelManager
|
||||
.getChannel('Arduino')
|
||||
.show({ preserveFocus: true });
|
||||
const result = await ExecuteWithProgress.doWithProgress({
|
||||
messageService: this.messageService,
|
||||
responseService: this.responseService,
|
||||
progressText,
|
||||
run: ({ progressId }) => task(progressId, this.coreService),
|
||||
keepOutput,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Contribution {
|
||||
|
||||
@@ -3,56 +3,47 @@ import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { BoardUserField, CoreService } from '../../common/protocol';
|
||||
import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus';
|
||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import {
|
||||
CoreServiceContribution,
|
||||
Command,
|
||||
CommandRegistry,
|
||||
MenuModelRegistry,
|
||||
KeybindingRegistry,
|
||||
TabBarToolbarRegistry,
|
||||
CoreServiceContribution,
|
||||
} from './contribution';
|
||||
import { UserFieldsDialog } from '../dialogs/user-fields/user-fields-dialog';
|
||||
import { DisposableCollection, nls } from '@theia/core/lib/common';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
import type { VerifySketchParams } from './verify-sketch';
|
||||
|
||||
@injectable()
|
||||
export class UploadSketch extends CoreServiceContribution {
|
||||
@inject(MenuModelRegistry)
|
||||
protected readonly menuRegistry: MenuModelRegistry;
|
||||
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
private readonly menuRegistry: MenuModelRegistry;
|
||||
|
||||
@inject(UserFieldsDialog)
|
||||
protected readonly userFieldsDialog: UserFieldsDialog;
|
||||
private readonly userFieldsDialog: UserFieldsDialog;
|
||||
|
||||
protected cachedUserFields: Map<string, BoardUserField[]> = new Map();
|
||||
private boardRequiresUserFields = false;
|
||||
private readonly cachedUserFields: Map<string, BoardUserField[]> = new Map();
|
||||
private readonly menuActionsDisposables = new DisposableCollection();
|
||||
|
||||
protected readonly onDidChangeEmitter = new Emitter<Readonly<void>>();
|
||||
readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
|
||||
protected uploadInProgress = false;
|
||||
protected boardRequiresUserFields = false;
|
||||
|
||||
protected readonly menuActionsDisposables = new DisposableCollection();
|
||||
private readonly onDidChangeEmitter = new Emitter<void>();
|
||||
private readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
private uploadInProgress = false;
|
||||
|
||||
protected override init(): void {
|
||||
super.init();
|
||||
this.boardsServiceClientImpl.onBoardsConfigChanged(async () => {
|
||||
this.boardsServiceProvider.onBoardsConfigChanged(async () => {
|
||||
const userFields =
|
||||
await this.boardsServiceClientImpl.selectedBoardUserFields();
|
||||
await this.boardsServiceProvider.selectedBoardUserFields();
|
||||
this.boardRequiresUserFields = userFields.length > 0;
|
||||
this.registerMenus(this.menuRegistry);
|
||||
});
|
||||
}
|
||||
|
||||
private selectedFqbnAddress(): string {
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const fqbn = boardsConfig.selectedBoard?.fqbn;
|
||||
if (!fqbn) {
|
||||
return '';
|
||||
@@ -76,7 +67,7 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
if (this.boardRequiresUserFields && !this.cachedUserFields.has(key)) {
|
||||
// Deep clone the array of board fields to avoid editing the cached ones
|
||||
this.userFieldsDialog.value = (
|
||||
await this.boardsServiceClientImpl.selectedBoardUserFields()
|
||||
await this.boardsServiceProvider.selectedBoardUserFields()
|
||||
).map((f) => ({ ...f }));
|
||||
const result = await this.userFieldsDialog.open();
|
||||
if (!result) {
|
||||
@@ -98,8 +89,7 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
const cached = this.cachedUserFields.get(key);
|
||||
// Deep clone the array of board fields to avoid editing the cached ones
|
||||
this.userFieldsDialog.value = (
|
||||
cached ??
|
||||
(await this.boardsServiceClientImpl.selectedBoardUserFields())
|
||||
cached ?? (await this.boardsServiceProvider.selectedBoardUserFields())
|
||||
).map((f) => ({ ...f }));
|
||||
|
||||
const result = await this.userFieldsDialog.open();
|
||||
@@ -130,7 +120,6 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
|
||||
override registerMenus(registry: MenuModelRegistry): void {
|
||||
this.menuActionsDisposables.dispose();
|
||||
|
||||
this.menuActionsDisposables.push(
|
||||
registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, {
|
||||
commandId: UploadSketch.Commands.UPLOAD_SKETCH.id,
|
||||
@@ -153,7 +142,7 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
new PlaceholderMenuNode(
|
||||
ArduinoMenus.SKETCH__MAIN_GROUP,
|
||||
// commandId: UploadSketch.Commands.UPLOAD_WITH_CONFIGURATION.id,
|
||||
UploadSketch.Commands.UPLOAD_WITH_CONFIGURATION.label!,
|
||||
UploadSketch.Commands.UPLOAD_WITH_CONFIGURATION.label,
|
||||
{ order: '2' }
|
||||
)
|
||||
)
|
||||
@@ -193,57 +182,42 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
}
|
||||
|
||||
async uploadSketch(usingProgrammer = false): Promise<void> {
|
||||
// even with buttons disabled, better to double check if an upload is already in progress
|
||||
if (this.uploadInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// toggle the toolbar button and menu item state.
|
||||
// uploadInProgress will be set to false whether the upload fails or not
|
||||
this.uploadInProgress = true;
|
||||
this.coreErrorHandler.reset();
|
||||
this.onDidChangeEmitter.fire();
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const [
|
||||
fqbn,
|
||||
{ selectedProgrammer },
|
||||
verify,
|
||||
uploadVerbose,
|
||||
sourceOverride,
|
||||
optimizeForDebug,
|
||||
compileVerbose,
|
||||
] = await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
),
|
||||
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
this.sourceOverride(),
|
||||
this.commandService.executeCommand<boolean>(
|
||||
'arduino-is-optimize-for-debug'
|
||||
),
|
||||
this.preferences.get('arduino.compile.verbose'),
|
||||
]);
|
||||
|
||||
const verbose = { compile: compileVerbose, upload: uploadVerbose };
|
||||
const board = {
|
||||
...boardsConfig.selectedBoard,
|
||||
name: boardsConfig.selectedBoard?.name || '',
|
||||
fqbn,
|
||||
};
|
||||
let options: CoreService.Upload.Options | undefined = undefined;
|
||||
const { selectedPort } = boardsConfig;
|
||||
const port = selectedPort;
|
||||
const userFields =
|
||||
this.cachedUserFields.get(this.selectedFqbnAddress()) ?? [];
|
||||
if (userFields.length === 0 && this.boardRequiresUserFields) {
|
||||
const verifyOptions =
|
||||
await this.commandService.executeCommand<CoreService.Options.Compile>(
|
||||
'arduino-verify-sketch',
|
||||
<VerifySketchParams>{
|
||||
exportBinaries: false,
|
||||
silent: true,
|
||||
}
|
||||
);
|
||||
if (!verifyOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uploadOptions = await this.uploadOptions(
|
||||
usingProgrammer,
|
||||
verifyOptions
|
||||
);
|
||||
if (!uploadOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: This does not belong here.
|
||||
// IDE2 should not do any preliminary checks but let the CLI fail and then toast a user consumable error message.
|
||||
if (
|
||||
uploadOptions.userFields.length === 0 &&
|
||||
this.boardRequiresUserFields
|
||||
) {
|
||||
this.messageService.error(
|
||||
nls.localize(
|
||||
'arduino/sketch/userFieldsNotFoundError',
|
||||
@@ -253,37 +227,13 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
return;
|
||||
}
|
||||
|
||||
if (usingProgrammer) {
|
||||
const programmer = selectedProgrammer;
|
||||
options = {
|
||||
sketch,
|
||||
board,
|
||||
optimizeForDebug: Boolean(optimizeForDebug),
|
||||
programmer,
|
||||
port,
|
||||
verbose,
|
||||
verify,
|
||||
sourceOverride,
|
||||
userFields,
|
||||
};
|
||||
} else {
|
||||
options = {
|
||||
sketch,
|
||||
board,
|
||||
optimizeForDebug: Boolean(optimizeForDebug),
|
||||
port,
|
||||
verbose,
|
||||
verify,
|
||||
sourceOverride,
|
||||
userFields,
|
||||
};
|
||||
}
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
if (usingProgrammer) {
|
||||
await this.coreService.uploadUsingProgrammer(options);
|
||||
} else {
|
||||
await this.coreService.upload(options);
|
||||
}
|
||||
await this.doWithProgress({
|
||||
progressText: nls.localize('arduino/sketch/uploading', 'Uploading...'),
|
||||
task: (progressId, coreService) =>
|
||||
coreService.upload({ ...uploadOptions, progressId }),
|
||||
keepOutput: true,
|
||||
});
|
||||
|
||||
this.messageService.info(
|
||||
nls.localize('arduino/sketch/doneUploading', 'Done uploading.'),
|
||||
{ timeout: 3000 }
|
||||
@@ -295,6 +245,52 @@ export class UploadSketch extends CoreServiceContribution {
|
||||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadOptions(
|
||||
usingProgrammer: boolean,
|
||||
verifyOptions: CoreService.Options.Compile
|
||||
): Promise<CoreService.Options.Upload | undefined> {
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return undefined;
|
||||
}
|
||||
const userFields = this.userFields();
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const [fqbn, { selectedProgrammer: programmer }, verify, verbose] =
|
||||
await Promise.all([
|
||||
verifyOptions.fqbn, // already decorated FQBN
|
||||
this.boardsDataStore.getData(this.sanitizeFqbn(verifyOptions.fqbn)),
|
||||
this.preferences.get('arduino.upload.verify'),
|
||||
this.preferences.get('arduino.upload.verbose'),
|
||||
]);
|
||||
const port = boardsConfig.selectedPort;
|
||||
return {
|
||||
sketch,
|
||||
fqbn,
|
||||
...(usingProgrammer && { programmer }),
|
||||
port,
|
||||
verbose,
|
||||
verify,
|
||||
userFields,
|
||||
};
|
||||
}
|
||||
|
||||
private userFields() {
|
||||
return this.cachedUserFields.get(this.selectedFqbnAddress()) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the `VENDOR:ARCHITECTURE:BOARD_ID[:MENU_ID=OPTION_ID[,MENU2_ID=OPTION_ID ...]]` FQBN to
|
||||
* `VENDOR:ARCHITECTURE:BOARD_ID` format.
|
||||
* See the details of the `{build.fqbn}` entry in the [specs](https://arduino.github.io/arduino-cli/latest/platform-specification/#global-predefined-properties).
|
||||
*/
|
||||
private sanitizeFqbn(fqbn: string | undefined): string | undefined {
|
||||
if (!fqbn) {
|
||||
return undefined;
|
||||
}
|
||||
const [vendor, arch, id] = fqbn.split(':');
|
||||
return `${vendor}:${arch}:${id}`;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace UploadSketch {
|
||||
@@ -302,7 +298,7 @@ export namespace UploadSketch {
|
||||
export const UPLOAD_SKETCH: Command = {
|
||||
id: 'arduino-upload-sketch',
|
||||
};
|
||||
export const UPLOAD_WITH_CONFIGURATION: Command = {
|
||||
export const UPLOAD_WITH_CONFIGURATION: Command & { label: string } = {
|
||||
id: 'arduino-upload-with-configuration-sketch',
|
||||
label: nls.localize(
|
||||
'arduino/sketch/configureAndUpload',
|
||||
|
||||
@@ -2,8 +2,6 @@ import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
|
||||
import { BoardsDataStore } from '../boards/boards-data-store';
|
||||
import { BoardsServiceProvider } from '../boards/boards-service-provider';
|
||||
import {
|
||||
CoreServiceContribution,
|
||||
Command,
|
||||
@@ -14,27 +12,36 @@ import {
|
||||
} from './contribution';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl';
|
||||
import { CoreService } from '../../common/protocol';
|
||||
import { CoreErrorHandler } from './core-error-handler';
|
||||
|
||||
export interface VerifySketchParams {
|
||||
/**
|
||||
* Same as `CoreService.Options.Compile#exportBinaries`
|
||||
*/
|
||||
readonly exportBinaries?: boolean;
|
||||
/**
|
||||
* If `true`, there won't be any UI indication of the verify command. It's `false` by default.
|
||||
*/
|
||||
readonly silent?: boolean;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class VerifySketch extends CoreServiceContribution {
|
||||
@inject(BoardsDataStore)
|
||||
protected readonly boardsDataStore: BoardsDataStore;
|
||||
@inject(CoreErrorHandler)
|
||||
private readonly coreErrorHandler: CoreErrorHandler;
|
||||
|
||||
@inject(BoardsServiceProvider)
|
||||
protected readonly boardsServiceClientImpl: BoardsServiceProvider;
|
||||
|
||||
protected readonly onDidChangeEmitter = new Emitter<Readonly<void>>();
|
||||
readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
|
||||
protected verifyInProgress = false;
|
||||
private readonly onDidChangeEmitter = new Emitter<void>();
|
||||
private readonly onDidChange = this.onDidChangeEmitter.event;
|
||||
private verifyInProgress = false;
|
||||
|
||||
override registerCommands(registry: CommandRegistry): void {
|
||||
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, {
|
||||
execute: () => this.verifySketch(),
|
||||
execute: (params?: VerifySketchParams) => this.verifySketch(params),
|
||||
isEnabled: () => !this.verifyInProgress,
|
||||
});
|
||||
registry.registerCommand(VerifySketch.Commands.EXPORT_BINARIES, {
|
||||
execute: () => this.verifySketch(true),
|
||||
execute: () => this.verifySketch({ exportBinaries: true }),
|
||||
isEnabled: () => !this.verifyInProgress,
|
||||
});
|
||||
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR, {
|
||||
@@ -84,61 +91,87 @@ export class VerifySketch extends CoreServiceContribution {
|
||||
});
|
||||
}
|
||||
|
||||
async verifySketch(exportBinaries?: boolean): Promise<void> {
|
||||
// even with buttons disabled, better to double check if a verify is already in progress
|
||||
protected override handleError(error: unknown): void {
|
||||
this.coreErrorHandler.tryHandle(error);
|
||||
super.handleError(error);
|
||||
}
|
||||
|
||||
private async verifySketch(
|
||||
params?: VerifySketchParams
|
||||
): Promise<CoreService.Options.Compile | undefined> {
|
||||
if (this.verifyInProgress) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// toggle the toolbar button and menu item state.
|
||||
// verifyInProgress will be set to false whether the compilation fails or not
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.verifyInProgress = true;
|
||||
if (!params?.silent) {
|
||||
this.verifyInProgress = true;
|
||||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
this.coreErrorHandler.reset();
|
||||
this.onDidChangeEmitter.fire();
|
||||
const { boardsConfig } = this.boardsServiceClientImpl;
|
||||
const [fqbn, sourceOverride] = await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(
|
||||
boardsConfig.selectedBoard?.fqbn
|
||||
|
||||
const options = await this.options(params?.exportBinaries);
|
||||
if (!options) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
await this.doWithProgress({
|
||||
progressText: nls.localize(
|
||||
'arduino/sketch/compile',
|
||||
'Compiling sketch...'
|
||||
),
|
||||
this.sourceOverride(),
|
||||
]);
|
||||
const board = {
|
||||
...boardsConfig.selectedBoard,
|
||||
name: boardsConfig.selectedBoard?.name || '',
|
||||
fqbn,
|
||||
};
|
||||
const verbose = this.preferences.get('arduino.compile.verbose');
|
||||
const compilerWarnings = this.preferences.get('arduino.compile.warnings');
|
||||
const optimizeForDebug =
|
||||
await this.commandService.executeCommand<boolean>(
|
||||
'arduino-is-optimize-for-debug'
|
||||
);
|
||||
this.outputChannelManager.getChannel('Arduino').clear();
|
||||
await this.coreService.compile({
|
||||
sketch,
|
||||
board,
|
||||
optimizeForDebug: Boolean(optimizeForDebug),
|
||||
verbose,
|
||||
exportBinaries,
|
||||
sourceOverride,
|
||||
compilerWarnings,
|
||||
task: (progressId, coreService) =>
|
||||
coreService.compile({
|
||||
...options,
|
||||
progressId,
|
||||
}),
|
||||
});
|
||||
this.messageService.info(
|
||||
nls.localize('arduino/sketch/doneCompiling', 'Done compiling.'),
|
||||
{ timeout: 3000 }
|
||||
);
|
||||
// Returns with the used options for the compilation
|
||||
// so that follow-up tasks (such as upload) can reuse the compiled code.
|
||||
// Note that the `fqbn` is already decorated with the board settings, if any.
|
||||
return options;
|
||||
} catch (e) {
|
||||
this.handleError(e);
|
||||
return undefined;
|
||||
} finally {
|
||||
this.verifyInProgress = false;
|
||||
this.onDidChangeEmitter.fire();
|
||||
if (!params?.silent) {
|
||||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async options(
|
||||
exportBinaries?: boolean
|
||||
): Promise<CoreService.Options.Compile | undefined> {
|
||||
const sketch = await this.sketchServiceClient.currentSketch();
|
||||
if (!CurrentSketch.isValid(sketch)) {
|
||||
return undefined;
|
||||
}
|
||||
const { boardsConfig } = this.boardsServiceProvider;
|
||||
const [fqbn, sourceOverride, optimizeForDebug] = await Promise.all([
|
||||
this.boardsDataStore.appendConfigToFqbn(boardsConfig.selectedBoard?.fqbn),
|
||||
this.sourceOverride(),
|
||||
this.commandService.executeCommand<boolean>(
|
||||
'arduino-is-optimize-for-debug'
|
||||
),
|
||||
]);
|
||||
const verbose = this.preferences.get('arduino.compile.verbose');
|
||||
const compilerWarnings = this.preferences.get('arduino.compile.warnings');
|
||||
return {
|
||||
sketch,
|
||||
fqbn,
|
||||
optimizeForDebug: Boolean(optimizeForDebug),
|
||||
verbose,
|
||||
exportBinaries,
|
||||
sourceOverride,
|
||||
compilerWarnings,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export namespace VerifySketch {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { CommandService } from '@theia/core/lib/common/command';
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import { ConfirmDialog } from '@theia/core/lib/browser/dialogs';
|
||||
import { Searchable } from '../../../common/protocol/searchable';
|
||||
import { ExecuteWithProgress } from '../../../common/protocol/progressible';
|
||||
import { Installable } from '../../../common/protocol/installable';
|
||||
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
|
||||
import { SearchBar } from './search-bar';
|
||||
@@ -111,7 +112,7 @@ export class FilterableListContainer<
|
||||
version: Installable.Version
|
||||
): Promise<void> {
|
||||
const { install, searchable } = this.props;
|
||||
await Installable.doWithProgress({
|
||||
await ExecuteWithProgress.doWithProgress({
|
||||
...this.props,
|
||||
progressText:
|
||||
nls.localize('arduino/common/processing', 'Processing') +
|
||||
@@ -137,7 +138,7 @@ export class FilterableListContainer<
|
||||
return;
|
||||
}
|
||||
const { uninstall, searchable } = this.props;
|
||||
await Installable.doWithProgress({
|
||||
await ExecuteWithProgress.doWithProgress({
|
||||
...this.props,
|
||||
progressText:
|
||||
nls.localize('arduino/common/processing', 'Processing') +
|
||||
|
||||
Reference in New Issue
Block a user