mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-11 19:29:28 +00:00
chore(deps): Updated to Theia 1.39.0 (#2144)
- update Theia to `1.39.0`, - remove the application packager and fix the security vulnerabilities, - bundle the backed application with `webpack`, and - enhance the developer docs. Co-authored-by: Akos Kitta <a.kitta@arduino.cc> Co-authored-by: per1234 <accounts@perglass.com> Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
import type { Disposable } from '@theia/core/lib/common/disposable';
|
||||
import type { AppInfo } from '../electron-common/electron-arduino';
|
||||
import type { StartupTasks } from '../electron-common/startup-task';
|
||||
import type { Sketch } from './contributions/contribution';
|
||||
|
||||
export type { AppInfo };
|
||||
|
||||
export const AppService = Symbol('AppService');
|
||||
export interface AppService {
|
||||
quit(): void;
|
||||
version(): Promise<string>;
|
||||
info(): Promise<AppInfo>;
|
||||
registerStartupTasksHandler(
|
||||
handler: (tasks: StartupTasks) => void
|
||||
): Disposable;
|
||||
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { EditorCommands } from '@theia/editor/lib/browser/editor-command';
|
||||
import { EditorMainMenu } from '@theia/editor/lib/browser/editor-menu';
|
||||
import { MonacoMenus } from '@theia/monaco/lib/browser/monaco-menu';
|
||||
@@ -69,7 +69,7 @@ export class ArduinoFrontendContribution
|
||||
private readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
protected init(): void {
|
||||
if (!window.navigator.onLine) {
|
||||
// tslint:disable-next-line:max-line-length
|
||||
this.messageService.warn(
|
||||
|
||||
@@ -355,10 +355,8 @@ import { StylingParticipant } from '@theia/core/lib/browser/styling-service';
|
||||
import { MonacoEditorMenuContribution } from './theia/monaco/monaco-menu';
|
||||
import { MonacoEditorMenuContribution as TheiaMonacoEditorMenuContribution } from '@theia/monaco/lib/browser/monaco-menu';
|
||||
import { UpdateArduinoState } from './contributions/update-arduino-state';
|
||||
import { TerminalWidgetImpl } from './theia/terminal/terminal-widget-impl';
|
||||
import { TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget';
|
||||
import { TerminalFrontendContribution } from './theia/terminal/terminal-frontend-contribution';
|
||||
import { TerminalFrontendContribution as TheiaTerminalFrontendContribution } from '@theia/terminal/lib/browser/terminal-frontend-contribution'
|
||||
import { TerminalFrontendContribution as TheiaTerminalFrontendContribution } from '@theia/terminal/lib/browser/terminal-frontend-contribution';
|
||||
|
||||
// Hack to fix copy/cut/paste issue after electron version update in Theia.
|
||||
// https://github.com/eclipse-theia/theia/issues/12487
|
||||
@@ -1032,7 +1030,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
);
|
||||
|
||||
// Patch terminal issues.
|
||||
rebind(TerminalWidget).to(TerminalWidgetImpl).inTransientScope();
|
||||
bind(TerminalFrontendContribution).toSelf().inSingletonScope();
|
||||
rebind(TheiaTerminalFrontendContribution).toService(TerminalFrontendContribution);
|
||||
rebind(TheiaTerminalFrontendContribution).toService(
|
||||
TerminalFrontendContribution
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { injectable, inject } from '@theia/core/shared/inversify';
|
||||
import { Emitter } from '@theia/core/lib/common/event';
|
||||
import { ReactWidget, Message } from '@theia/core/lib/browser';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { Event } from '@theia/core/lib/common/event';
|
||||
import { notEmpty } from '@theia/core/lib/common/objects';
|
||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import * as ReactDOM from '@theia/core/shared/react-dom';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
|
||||
export type ProgressBarProps = {
|
||||
percent?: number;
|
||||
|
||||
@@ -4,7 +4,6 @@ import { nls } from '@theia/core/lib/common/nls';
|
||||
import { isOSX, isWindows } from '@theia/core/lib/common/os';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import moment from 'moment';
|
||||
import { ConfigService } from '../../common/protocol';
|
||||
import { AppService } from '../app-service';
|
||||
import { ArduinoMenus } from '../menu/arduino-menus';
|
||||
import {
|
||||
@@ -18,8 +17,6 @@ import {
|
||||
export class About extends Contribution {
|
||||
@inject(ClipboardService)
|
||||
private readonly clipboardService: ClipboardService;
|
||||
@inject(ConfigService)
|
||||
private readonly configService: ConfigService;
|
||||
@inject(AppService)
|
||||
private readonly appService: AppService;
|
||||
|
||||
@@ -42,11 +39,9 @@ export class About extends Contribution {
|
||||
}
|
||||
|
||||
private async showAbout(): Promise<void> {
|
||||
const [appVersion, cliVersion] = await Promise.all([
|
||||
this.appService.version(),
|
||||
this.configService.getVersion(),
|
||||
]);
|
||||
const buildDate = this.buildDate;
|
||||
const appInfo = await this.appService.info();
|
||||
const { appVersion, cliVersion, buildDate } = appInfo;
|
||||
|
||||
const detail = (showAll: boolean) =>
|
||||
nls.localize(
|
||||
'arduino/about/detail',
|
||||
@@ -84,10 +79,6 @@ export class About extends Contribution {
|
||||
return FrontendApplicationConfigProvider.get().applicationName;
|
||||
}
|
||||
|
||||
private get buildDate(): string | undefined {
|
||||
return FrontendApplicationConfigProvider.get().buildDate;
|
||||
}
|
||||
|
||||
private ago(isoTime: string): string {
|
||||
const now = moment(Date.now());
|
||||
const other = moment(isoTime);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
|
||||
export const CertificateAddComponent = ({
|
||||
addCertificate,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
|
||||
export const CertificateListComponent = ({
|
||||
certificates,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import Tippy from '@tippyjs/react';
|
||||
import { AvailableBoard } from '../../boards/boards-service-provider';
|
||||
import { CertificateListComponent } from './certificate-list';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { AvailableBoard } from '../../boards/boards-service-provider';
|
||||
import { ArduinoSelect } from '../../widgets/arduino-select';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { nls } from '@theia/core/lib/common/nls';
|
||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||
import { Widget } from '@theia/core/shared/@phosphor/widgets';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { CreateApi } from '../create/create-api';
|
||||
import { AbstractDialog } from '../theia/dialogs/dialogs';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { Port } from '../../../common/protocol';
|
||||
import {
|
||||
ArduinoFirmwareUploader,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
// @ts-expect-error see https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1319854183
|
||||
import type { Options } from 'react-markdown';
|
||||
import { ProgressInfo, UpdateInfo } from '../../../common/protocol/ide-updater';
|
||||
@@ -111,7 +111,6 @@ export const IDEUpdaterComponent = ({
|
||||
>
|
||||
<ReactMarkdown
|
||||
components={{
|
||||
// @ts-expect-error see imports. There is no ESM type-only import in CommonJS modules.
|
||||
a: ({ href, children, ...props }) => (
|
||||
<a onClick={() => href && openExternal(href)} {...props}>
|
||||
{children}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
||||
import 'react-tabs/style/react-tabs.css';
|
||||
import { Disable } from 'react-disable';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
injectable,
|
||||
inject,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
interface SettingsStepInputProps {
|
||||
|
||||
@@ -117,7 +117,7 @@ export class SettingsService {
|
||||
protected _settings: Settings;
|
||||
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
protected init(): void {
|
||||
this.appStateService.reachedState('ready').then(async () => {
|
||||
const settings = await this.loadSettings();
|
||||
this._settings = deepClone(settings);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { BoardUserField } from '../../../common/protocol';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { DialogProps } from '@theia/core/lib/browser/dialogs';
|
||||
import { Message } from '@theia/core/shared/@phosphor/messaging';
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
injectable,
|
||||
inject,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import {
|
||||
AbstractViewContribution,
|
||||
ApplicationShell,
|
||||
codicon
|
||||
codicon,
|
||||
} from '@theia/core/lib/browser';
|
||||
import { MonitorWidget } from './monitor-widget';
|
||||
import { MenuModelRegistry, Command, CommandRegistry } from '@theia/core';
|
||||
@@ -20,7 +24,7 @@ import { MonitorManagerProxyClient } from '../../../common/protocol';
|
||||
import {
|
||||
ArduinoPreferences,
|
||||
defaultMonitorWidgetDockPanel,
|
||||
isMonitorWidgetDockPanel
|
||||
isMonitorWidgetDockPanel,
|
||||
} from '../../arduino-preferences';
|
||||
import { serialMonitorWidgetLabel } from '../../../common/nls';
|
||||
|
||||
@@ -60,7 +64,7 @@ export class MonitorViewContribution
|
||||
static readonly TOGGLE_SERIAL_MONITOR_TOOLBAR =
|
||||
MonitorWidget.ID + ':toggle-toolbar';
|
||||
static readonly RESET_SERIAL_MONITOR = MonitorWidget.ID + ':reset';
|
||||
|
||||
|
||||
@inject(MonitorModel)
|
||||
private readonly model: MonitorModel;
|
||||
@inject(MonitorManagerProxyClient)
|
||||
@@ -85,10 +89,16 @@ export class MonitorViewContribution
|
||||
|
||||
@postConstruct()
|
||||
protected init(): void {
|
||||
this._panel = this.arduinoPreferences['arduino.monitor.dockPanel'] ?? defaultMonitorWidgetDockPanel;
|
||||
this._panel =
|
||||
this.arduinoPreferences['arduino.monitor.dockPanel'] ??
|
||||
defaultMonitorWidgetDockPanel;
|
||||
this.monitorManagerProxy.onMonitorShouldReset(() => this.reset());
|
||||
this.arduinoPreferences.onPreferenceChanged((event) => {
|
||||
if (event.preferenceName === 'arduino.monitor.dockPanel' && isMonitorWidgetDockPanel(event.newValue) && event.newValue !== this._panel) {
|
||||
if (
|
||||
event.preferenceName === 'arduino.monitor.dockPanel' &&
|
||||
isMonitorWidgetDockPanel(event.newValue) &&
|
||||
event.newValue !== this._panel
|
||||
) {
|
||||
this._panel = event.newValue;
|
||||
const widget = this.tryGetWidget();
|
||||
// reopen at the new position if opened
|
||||
@@ -97,14 +107,14 @@ export class MonitorViewContribution
|
||||
this.openView({ activate: true, reveal: true });
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
override get defaultViewOptions(): ApplicationShell.WidgetOptions {
|
||||
const viewOptions = super.defaultViewOptions;
|
||||
return {
|
||||
...viewOptions,
|
||||
area: this._panel
|
||||
area: this._panel,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
injectable,
|
||||
inject,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { Key, KeyCode } from '@theia/core/lib/browser/keys';
|
||||
import { Board } from '../../../common/protocol/boards-service';
|
||||
import { DisposableCollection, nls } from '@theia/core/lib/common';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { Event } from '@theia/core/lib/common/event';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { areEqual, FixedSizeList as List } from 'react-window';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog';
|
||||
|
||||
export class AboutDialog extends TheiaAboutDialog {
|
||||
protected override async init(): Promise<void> {
|
||||
protected override init(): void {
|
||||
// NOOP
|
||||
// IDE2 has a custom about dialog, so it does not make sense to collect Theia extensions at startup time.
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat
|
||||
private readonly connectionProvider: WebSocketConnectionProvider;
|
||||
|
||||
@postConstruct()
|
||||
protected override async init(): Promise<void> {
|
||||
protected override init(): void {
|
||||
this.schedulePing();
|
||||
const refresh = debounce(() => {
|
||||
this.updateStatus(Boolean(this.daemonPort.port) && this.isOnline.online);
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { accountMenu } from '../../contributions/account';
|
||||
import { CreateFeatures } from '../../create/create-features';
|
||||
import { ApplicationConnectionStatusContribution } from './connection-status-service';
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import debounce from 'p-debounce';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
import { Event, Emitter } from '@theia/core/lib/common/event';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
@@ -42,9 +38,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager {
|
||||
return this.onTempContentDidChangeEmitter.event;
|
||||
}
|
||||
|
||||
@postConstruct()
|
||||
protected override async init(): Promise<void> {
|
||||
super.init();
|
||||
protected override async doInit(): Promise<void> {
|
||||
this.appStateService.reachedState('ready').then(async () => {
|
||||
const tempContent = await this.getTempLaunchJsonContent();
|
||||
if (!tempContent) {
|
||||
@@ -78,6 +72,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager {
|
||||
});
|
||||
this.updateModels();
|
||||
});
|
||||
return super.doInit();
|
||||
}
|
||||
|
||||
protected override updateModels = debounce(async () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DisposableCollection,
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { createRoot } from '@theia/core/shared/react-dom/client';
|
||||
|
||||
@injectable()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { NotificationComponent } from './notification-component';
|
||||
import { NotificationCenterComponent as TheiaNotificationCenterComponent } from '@theia/messages/lib/browser/notification-center-component';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { NotificationComponent as TheiaNotificationComponent } from '@theia/messages/lib/browser/notification-component';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { codicon } from '@theia/core/lib/browser';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { NotificationComponent } from './notification-component';
|
||||
import { NotificationToastsComponent as TheiaNotificationToastsComponent } from '@theia/messages/lib/browser/notification-toasts-component';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class PreferenceTreeGenerator extends TheiaPreferenceTreeGenerator {
|
||||
@inject(FrontendApplicationStateService)
|
||||
private readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
protected override async init(): Promise<void> {
|
||||
protected override init(): void {
|
||||
this.appStateService.onStateChanged((state) => {
|
||||
this.state = state;
|
||||
// manually trigger a model (and UI) refresh if it was requested during the startup phase.
|
||||
|
||||
@@ -1,38 +1,16 @@
|
||||
import { TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
||||
import { CommandRegistry } from '@theia/core/lib/common/command';
|
||||
import { Widget } from '@theia/core/shared/@phosphor/widgets';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget';
|
||||
import {
|
||||
TerminalCommands,
|
||||
TerminalFrontendContribution as TheiaTerminalFrontendContribution,
|
||||
} from '@theia/terminal/lib/browser/terminal-frontend-contribution';
|
||||
|
||||
// Patch for https://github.com/eclipse-theia/theia/pull/12626
|
||||
@injectable()
|
||||
export class TerminalFrontendContribution extends TheiaTerminalFrontendContribution {
|
||||
override registerCommands(commands: CommandRegistry): void {
|
||||
super.registerCommands(commands);
|
||||
commands.unregisterCommand(TerminalCommands.SPLIT);
|
||||
commands.registerCommand(TerminalCommands.SPLIT, {
|
||||
execute: () => this.splitTerminal(),
|
||||
isEnabled: (w) => this.withWidget(w, () => true),
|
||||
isVisible: (w) => this.withWidget(w, () => true),
|
||||
});
|
||||
}
|
||||
|
||||
override registerToolbarItems(toolbar: TabBarToolbarRegistry): void {
|
||||
super.registerToolbarItems(toolbar);
|
||||
// removes the `split-terminal` command from the tabbar toolbar
|
||||
// https://github.com/dankeboy36/esp-exception-decoder/pull/1#pullrequestreview-1500146673
|
||||
toolbar.unregisterItem(TerminalCommands.SPLIT.id);
|
||||
}
|
||||
|
||||
private withWidget<T>(
|
||||
widget: Widget | undefined,
|
||||
fn: (widget: TerminalWidget) => T
|
||||
): T | false {
|
||||
if (widget instanceof TerminalWidget) {
|
||||
return fn(widget);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { TerminalWidgetImpl as TheiaTerminalWidgetImpl } from '@theia/terminal/lib/browser/terminal-widget-impl';
|
||||
import debounce from 'p-debounce';
|
||||
|
||||
// Patch for https://github.com/eclipse-theia/theia/pull/12587
|
||||
@injectable()
|
||||
export class TerminalWidgetImpl extends TheiaTerminalWidgetImpl {
|
||||
private readonly debouncedResizeTerminal = debounce(
|
||||
() => this.doResizeTerminal(),
|
||||
50
|
||||
);
|
||||
|
||||
protected override resizeTerminal(): void {
|
||||
this.debouncedResizeTerminal();
|
||||
}
|
||||
|
||||
private doResizeTerminal(): void {
|
||||
const geo = this.fitAddon.proposeDimensions();
|
||||
const cols = geo.cols;
|
||||
const rows = geo.rows - 1; // subtract one row for margin
|
||||
this.term.resize(cols, rows);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@ export class WorkspaceInputDialog extends TheiaWorkspaceInputDialog {
|
||||
protected override readonly labelProvider: LabelProvider
|
||||
) {
|
||||
super(props, labelProvider);
|
||||
if (this.contentNode.contains(this.errorMessageNode)) {
|
||||
// Reverts https://github.com/eclipse-theia/theia/pull/12585/files#diff-068570364d86f936ca72dfc52f8bfa93f14f6d971e2e6fa19216f33cb322244bR533-R534
|
||||
this.contentNode.removeChild(this.errorMessageNode);
|
||||
this.controlPanel.prepend(this.errorMessageNode);
|
||||
}
|
||||
this.node.classList.add('workspace-input-dialog');
|
||||
this.appendCloseButton(Dialog.CANCEL);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
TabBarToolbar,
|
||||
TabBarToolbarRegistry,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import type { Props, StylesConfig, ThemeConfig } from 'react-select';
|
||||
import Select from 'react-select';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import type { Root } from '@theia/core/shared/react-dom/client';
|
||||
import {
|
||||
inject,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { TreeModel } from '@theia/core/lib/browser/tree/tree-model';
|
||||
import { CloudSketchbookTreeModel } from './cloud-sketchbook-tree-model';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { CloudSketchbookTreeModel } from './cloud-sketchbook-tree-model';
|
||||
import { AuthenticationClientService } from '../../auth/authentication-client-service';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import type { ArduinoComponent } from '../../../common/protocol/arduino-component';
|
||||
import { Installable } from '../../../common/protocol/installable';
|
||||
import type { ListItemRenderer } from './list-item-renderer';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { Virtuoso } from '@theia/core/shared/react-virtuoso';
|
||||
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
|
||||
import { Installable } from '../../../common/protocol/installable';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
BoardSearch,
|
||||
LibrarySearch,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { Event } from '@theia/core/lib/common/event';
|
||||
import { CommandService } from '@theia/core/lib/common/command';
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { Unknown } from '../../../common/nls';
|
||||
import {
|
||||
CoreService,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
injectable,
|
||||
postConstruct,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
|
||||
export class SearchBar extends React.Component<SearchBar.Props> {
|
||||
constructor(props: Readonly<SearchBar.Props>) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
|
||||
export class CreateNew extends React.Component<CreateNew.Props> {
|
||||
override render(): React.ReactNode {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import { createRoot, Root } from '@theia/core/shared/react-dom/client';
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { nls } from '@theia/core/lib/common/nls';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as React from '@theia/core/shared/react';
|
||||
import React from '@theia/core/shared/react';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
@@ -62,12 +62,16 @@ export class SketchbookTreeWidget extends FileTreeWidget {
|
||||
}
|
||||
|
||||
@postConstruct()
|
||||
protected override async init(): Promise<void> {
|
||||
protected override init(): void {
|
||||
super.init();
|
||||
// cache the current open sketch uri
|
||||
const currentSketch = await this.sketchServiceClient.currentSketch();
|
||||
this.currentSketchUri =
|
||||
(CurrentSketch.isValid(currentSketch) && currentSketch.uri) || '';
|
||||
this.sketchServiceClient
|
||||
.currentSketch()
|
||||
.then(
|
||||
(currentSketch) =>
|
||||
(this.currentSketchUri =
|
||||
(CurrentSketch.isValid(currentSketch) && currentSketch.uri) || '')
|
||||
);
|
||||
}
|
||||
|
||||
protected override createNodeClassNames(
|
||||
|
||||
@@ -3,7 +3,6 @@ import { RecursivePartial } from '@theia/core/lib/common/types';
|
||||
export const ConfigServicePath = '/services/config-service';
|
||||
export const ConfigService = Symbol('ConfigService');
|
||||
export interface ConfigService {
|
||||
getVersion(): Promise<Readonly<string>>;
|
||||
getConfiguration(): Promise<ConfigState>;
|
||||
setConfiguration(config: Config): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Disposable } from '@theia/core/lib/common/disposable';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import type { AppService } from '../browser/app-service';
|
||||
import type { AppInfo, AppService } from '../browser/app-service';
|
||||
import type { Sketch } from '../common/protocol/sketches-service';
|
||||
import type { StartupTasks } from '../electron-common/startup-task';
|
||||
|
||||
@@ -10,8 +10,8 @@ export class ElectronAppService implements AppService {
|
||||
window.electronArduino.quitApp();
|
||||
}
|
||||
|
||||
version(): Promise<string> {
|
||||
return window.electronArduino.appVersion();
|
||||
info(): Promise<AppInfo> {
|
||||
return window.electronArduino.appInfo();
|
||||
}
|
||||
|
||||
registerStartupTasksHandler(
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { v4 } from 'uuid';
|
||||
import type { Sketch } from '../common/protocol/sketches-service';
|
||||
import {
|
||||
CHANNEL_APP_VERSION,
|
||||
CHANNEL_APP_INFO,
|
||||
CHANNEL_IS_FIRST_WINDOW,
|
||||
CHANNEL_MAIN_MENU_ITEM_DID_CLICK,
|
||||
CHANNEL_OPEN_PATH,
|
||||
@@ -76,7 +76,7 @@ const api: ElectronArduino = {
|
||||
ipcRenderer.invoke(CHANNEL_SHOW_OPEN_DIALOG, options),
|
||||
showSaveDialog: (options: SaveDialogOptions) =>
|
||||
ipcRenderer.invoke(CHANNEL_SHOW_SAVE_DIALOG, options),
|
||||
appVersion: () => ipcRenderer.invoke(CHANNEL_APP_VERSION),
|
||||
appInfo: () => ipcRenderer.invoke(CHANNEL_APP_INFO),
|
||||
quitApp: () => ipcRenderer.send(CHANNEL_QUIT_APP),
|
||||
isFirstWindow: () => ipcRenderer.invoke(CHANNEL_IS_FIRST_WINDOW),
|
||||
requestReload: (options: StartupTasks) =>
|
||||
|
||||
@@ -11,6 +11,17 @@ import type {
|
||||
InternalMenuDto as TheiaInternalMenuDto,
|
||||
MenuDto,
|
||||
} from '@theia/core/lib/electron-common/electron-api';
|
||||
|
||||
export const appInfoPropertyLiterals = [
|
||||
'appVersion',
|
||||
'cliVersion',
|
||||
'buildDate',
|
||||
] as const;
|
||||
export type AppInfoProperty = (typeof appInfoPropertyLiterals)[number];
|
||||
export type AppInfo = {
|
||||
readonly [P in AppInfoProperty]: string;
|
||||
};
|
||||
|
||||
import type { Sketch } from '../common/protocol/sketches-service';
|
||||
import type { StartupTasks } from './startup-task';
|
||||
|
||||
@@ -50,7 +61,7 @@ export interface ElectronArduino {
|
||||
showMessageBox(options: MessageBoxOptions): Promise<MessageBoxReturnValue>;
|
||||
showOpenDialog(options: OpenDialogOptions): Promise<OpenDialogReturnValue>;
|
||||
showSaveDialog(options: SaveDialogOptions): Promise<SaveDialogReturnValue>;
|
||||
appVersion(): Promise<string>;
|
||||
appInfo(): Promise<AppInfo>;
|
||||
quitApp(): void;
|
||||
isFirstWindow(): Promise<boolean>;
|
||||
requestReload(tasks: StartupTasks): void;
|
||||
@@ -77,7 +88,7 @@ declare global {
|
||||
export const CHANNEL_SHOW_MESSAGE_BOX = 'Arduino:ShowMessageBox';
|
||||
export const CHANNEL_SHOW_OPEN_DIALOG = 'Arduino:ShowOpenDialog';
|
||||
export const CHANNEL_SHOW_SAVE_DIALOG = 'Arduino:ShowSaveDialog';
|
||||
export const CHANNEL_APP_VERSION = 'Arduino:AppVersion';
|
||||
export const CHANNEL_APP_INFO = 'Arduino:AppInfo';
|
||||
export const CHANNEL_QUIT_APP = 'Arduino:QuitApp';
|
||||
export const CHANNEL_IS_FIRST_WINDOW = 'Arduino:IsFirstWindow';
|
||||
export const CHANNEL_SCHEDULE_DELETION = 'Arduino:ScheduleDeletion';
|
||||
|
||||
@@ -18,7 +18,8 @@ import { createDisposableListener } from '@theia/core/lib/electron-main/event-ut
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { WebContents } from '@theia/electron/shared/electron';
|
||||
import {
|
||||
CHANNEL_APP_VERSION,
|
||||
AppInfo,
|
||||
CHANNEL_APP_INFO,
|
||||
CHANNEL_IS_FIRST_WINDOW,
|
||||
CHANNEL_MAIN_MENU_ITEM_DID_CLICK,
|
||||
CHANNEL_OPEN_PATH,
|
||||
@@ -85,8 +86,8 @@ export class ElectronArduino implements ElectronMainApplicationContribution {
|
||||
return result;
|
||||
}
|
||||
);
|
||||
ipcMain.handle(CHANNEL_APP_VERSION, async () => {
|
||||
return app.appVersion;
|
||||
ipcMain.handle(CHANNEL_APP_INFO, async (): Promise<AppInfo> => {
|
||||
return app.appInfo;
|
||||
});
|
||||
ipcMain.on(CHANNEL_QUIT_APP, () => app.requestStop());
|
||||
ipcMain.handle(CHANNEL_IS_FIRST_WINDOW, async (event) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { fork } from 'node:child_process';
|
||||
import { AddressInfo } from 'node:net';
|
||||
import { join, isAbsolute, resolve } from 'node:path';
|
||||
import { promises as fs, rm, rmSync } from 'node:fs';
|
||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||
import type { MaybePromise, Mutable } from '@theia/core/lib/common/types';
|
||||
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
|
||||
import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
|
||||
import {
|
||||
@@ -31,6 +31,8 @@ import {
|
||||
} from '@theia/core/lib/common/disposable';
|
||||
import { Sketch } from '../../common/protocol';
|
||||
import {
|
||||
AppInfo,
|
||||
appInfoPropertyLiterals,
|
||||
CHANNEL_PLOTTER_WINDOW_DID_CLOSE,
|
||||
CHANNEL_SCHEDULE_DELETION,
|
||||
CHANNEL_SHOW_PLOTTER_WINDOW,
|
||||
@@ -72,6 +74,11 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
private readonly isTempSketch: IsTempSketch;
|
||||
private startup = false;
|
||||
private _firstWindowId: number | undefined;
|
||||
private _appInfo: AppInfo = {
|
||||
appVersion: '',
|
||||
cliVersion: '',
|
||||
buildDate: '',
|
||||
};
|
||||
private openFilePromise = new Deferred();
|
||||
/**
|
||||
* It contains all things the IDE2 must clean up before a normal stop.
|
||||
@@ -111,7 +118,8 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
const cwd = process.cwd();
|
||||
this.attachFileAssociations(cwd);
|
||||
this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native';
|
||||
this._config = config;
|
||||
this._config = await updateFrontendApplicationConfigFromPackageJson(config);
|
||||
this._appInfo = updateAppInfo(this._appInfo, this._config);
|
||||
this.hookApplicationEvents();
|
||||
const [port] = await Promise.all([this.startBackend(), app.whenReady()]);
|
||||
this.startContentTracing();
|
||||
@@ -615,8 +623,8 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
return this._firstWindowId;
|
||||
}
|
||||
|
||||
get appVersion(): string {
|
||||
return app.getVersion();
|
||||
get appInfo(): AppInfo {
|
||||
return this._appInfo;
|
||||
}
|
||||
|
||||
private async delete(sketch: Sketch): Promise<void> {
|
||||
@@ -681,3 +689,84 @@ class InterruptWorkspaceRestoreError extends Error {
|
||||
Object.setPrototypeOf(this, InterruptWorkspaceRestoreError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a workaround for a limitation with the Theia CLI and `electron-builder`.
|
||||
// It is possible to run the `electron-builder` with `-c.extraMetadata.foo.bar=36` option.
|
||||
// On the fly, a `package.json` file will be generated for the final bundled application with the additional `{ "foo": { "bar": 36 } }` metadata.
|
||||
// The Theia build (via the CLI) requires the extra `foo.bar=36` metadata to be in the `package.json` at build time (before `electron-builder` time).
|
||||
// See the generated `./electron-app/src-gen/backend/electron-main.js` and how this works.
|
||||
// This method merges in any additional required properties defined in the current! `package.json` of the application. For example, the `buildDate`.
|
||||
// The current package.json is the package.json of the `electron-app` if running from the source code,
|
||||
// but it's the `package.json` inside the `resources/app/` folder if it's the final bundled app.
|
||||
// See https://github.com/arduino/arduino-ide/pull/2144#pullrequestreview-1556343430.
|
||||
async function updateFrontendApplicationConfigFromPackageJson(
|
||||
config: FrontendApplicationConfig
|
||||
): Promise<FrontendApplicationConfig> {
|
||||
try {
|
||||
const modulePath = __filename;
|
||||
// must go from `./lib/backend/electron-main.js` to `./package.json` when the app is webpacked.
|
||||
const packageJsonPath = join(modulePath, '..', '..', '..', 'package.json');
|
||||
console.debug(
|
||||
`Checking for frontend application configuration customizations. Module path: ${modulePath}, destination 'package.json': ${packageJsonPath}`
|
||||
);
|
||||
const rawPackageJson = await fs.readFile(packageJsonPath, {
|
||||
encoding: 'utf8',
|
||||
});
|
||||
const packageJson = JSON.parse(rawPackageJson);
|
||||
if (packageJson?.theia?.frontend?.config) {
|
||||
const packageJsonConfig: Record<string, string> =
|
||||
packageJson?.theia?.frontend?.config;
|
||||
for (const property of appInfoPropertyLiterals) {
|
||||
const value = packageJsonConfig[property];
|
||||
if (value && !config[property]) {
|
||||
if (!config[property]) {
|
||||
console.debug(
|
||||
`Setting 'theia.frontend.config.${property}' application configuration value to: ${JSON.stringify(
|
||||
value
|
||||
)} (type of ${typeof value})`
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
`Overriding 'theia.frontend.config.${property}' application configuration value with: ${JSON.stringify(
|
||||
value
|
||||
)} (type of ${typeof value}). Original value: ${JSON.stringify(
|
||||
config[property]
|
||||
)}`
|
||||
);
|
||||
}
|
||||
config[property] = value;
|
||||
}
|
||||
}
|
||||
console.debug(
|
||||
`Frontend application configuration after modifications: ${JSON.stringify(
|
||||
config
|
||||
)}`
|
||||
);
|
||||
return config;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Could not read the frontend application configuration from the 'package.json' file. Falling back to (the Theia CLI) generated default config: ${JSON.stringify(
|
||||
config
|
||||
)}`,
|
||||
err
|
||||
);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutates the `toUpdate` argument and returns with it.
|
||||
*/
|
||||
function updateAppInfo(
|
||||
toUpdate: Mutable<AppInfo>,
|
||||
updateWith: Record<string, unknown>
|
||||
): AppInfo {
|
||||
appInfoPropertyLiterals.forEach((property) => {
|
||||
const newValue = updateWith[property];
|
||||
if (typeof newValue === 'string') {
|
||||
toUpdate[property] = newValue;
|
||||
}
|
||||
});
|
||||
return toUpdate;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
|
||||
import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application';
|
||||
import { ArduinoDaemon, NotificationServiceServer } from '../common/protocol';
|
||||
import { CLI_CONFIG } from './cli-config';
|
||||
import { getExecPath } from './exec-util';
|
||||
import { SettingsReader } from './settings-reader';
|
||||
import { ProcessUtils } from '@theia/core/lib/node/process-utils';
|
||||
import { arduinoCliPath } from './resources';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoDaemonImpl
|
||||
@@ -133,7 +133,7 @@ export class ArduinoDaemonImpl
|
||||
}
|
||||
|
||||
getExecPath(): string {
|
||||
return getExecPath('arduino-cli');
|
||||
return arduinoCliPath;
|
||||
}
|
||||
|
||||
protected async getSpawnArgs(): Promise<string[]> {
|
||||
|
||||
@@ -5,8 +5,9 @@ import {
|
||||
ArduinoFirmwareUploader,
|
||||
FirmwareInfo,
|
||||
} from '../common/protocol/arduino-firmware-uploader';
|
||||
import { getExecPath, spawnCommand } from './exec-util';
|
||||
import { spawnCommand } from './exec-util';
|
||||
import { MonitorManager } from './monitor-manager';
|
||||
import { arduinoFirmwareUploaderPath } from './resources';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoFirmwareUploaderImpl implements ArduinoFirmwareUploader {
|
||||
@@ -74,7 +75,10 @@ export class ArduinoFirmwareUploaderImpl implements ArduinoFirmwareUploader {
|
||||
}
|
||||
|
||||
private async runCommand(args: string[]): Promise<string> {
|
||||
const execPath = getExecPath('arduino-fwuploader');
|
||||
return await spawnCommand(execPath, args, this.onError.bind(this));
|
||||
return await spawnCommand(
|
||||
arduinoFirmwareUploaderPath,
|
||||
args,
|
||||
this.onError.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ import {
|
||||
SurveyNotificationServicePath,
|
||||
} from '../common/protocol/survey-service';
|
||||
import { IsTempSketch } from './is-temp-sketch';
|
||||
import { rebindNsfwFileSystemWatcher } from './theia/filesystem/nsfw-watcher/nsfw-bindings';
|
||||
import { rebindNsfwFileSystemWatcher } from './theia/filesystem/nsfw-bindings';
|
||||
import { MessagingContribution } from './theia/core/messaging-contribution';
|
||||
import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service';
|
||||
import { HostedPluginReader } from './theia/plugin-ext/plugin-reader';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as http from 'node:http';
|
||||
import * as url from 'node:url';
|
||||
import http from 'node:http';
|
||||
import url from 'node:url';
|
||||
import { body } from './body';
|
||||
import { authServerPort } from '../../common/protocol/authentication-service';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type * as keytarType from 'keytar';
|
||||
import type keytarType from 'keytar';
|
||||
|
||||
export type KeychainConfig = {
|
||||
credentialsSection: string;
|
||||
@@ -6,9 +6,9 @@ export type KeychainConfig = {
|
||||
};
|
||||
|
||||
type Keytar = {
|
||||
getPassword: typeof keytarType['getPassword'];
|
||||
setPassword: typeof keytarType['setPassword'];
|
||||
deletePassword: typeof keytarType['deletePassword'];
|
||||
getPassword: (typeof keytarType)['getPassword'];
|
||||
setPassword: (typeof keytarType)['setPassword'];
|
||||
deletePassword: (typeof keytarType)['deletePassword'];
|
||||
};
|
||||
|
||||
export class Keychain {
|
||||
|
||||
@@ -6,7 +6,9 @@ import { constants, promises as fs } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { ConfigService } from '../common/protocol';
|
||||
import { Formatter, FormatterOptions } from '../common/protocol/formatter';
|
||||
import { getExecPath, spawnCommand } from './exec-util';
|
||||
import { spawnCommand } from './exec-util';
|
||||
import { clangFormatPath } from './resources';
|
||||
import defaultClangFormat from './default-formatter-config.json';
|
||||
|
||||
@injectable()
|
||||
export class ClangFormatter implements Formatter {
|
||||
@@ -37,7 +39,7 @@ export class ClangFormatter implements Formatter {
|
||||
}
|
||||
|
||||
private execPath(): string {
|
||||
return getExecPath('clang-format');
|
||||
return clangFormatPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,10 +131,9 @@ function styleJson({
|
||||
TabWidth,
|
||||
UseTab,
|
||||
}: ClangFormatOptions): Record<string, unknown> {
|
||||
// Source: https://github.com/arduino/tooling-project-assets/tree/main/other/clang-format-configuration
|
||||
const defaultConfig = require('../../src/node/default-formatter-config.json');
|
||||
return {
|
||||
...defaultConfig,
|
||||
// Source: https://github.com/arduino/tooling-project-assets/tree/main/other/clang-format-configuration
|
||||
...defaultClangFormat,
|
||||
TabWidth,
|
||||
UseTab,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { promises as fs } from 'node:fs';
|
||||
import { dirname } from 'node:path';
|
||||
import * as yaml from 'js-yaml';
|
||||
import yaml from 'js-yaml';
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import { injectable, inject, named } from '@theia/core/shared/inversify';
|
||||
import URI from '@theia/core/lib/common/uri';
|
||||
@@ -131,10 +131,6 @@ export class ConfigServiceImpl
|
||||
return this.configChangeEmitter.event;
|
||||
}
|
||||
|
||||
async getVersion(): Promise<string> {
|
||||
return require('../../package.json').arduino?.cli?.version || '';
|
||||
}
|
||||
|
||||
private async initConfig(): Promise<void> {
|
||||
this.logger.info('>>> Initializing CLI configuration...');
|
||||
try {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import { join } from 'node:path';
|
||||
import * as fs from 'node:fs';
|
||||
import fs from 'node:fs';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import {
|
||||
SketchRef,
|
||||
@@ -15,6 +15,7 @@ import { LibraryLocation, LibraryPackage } from '../common/protocol';
|
||||
import { URI } from '@theia/core/lib/common/uri';
|
||||
import { Path } from '@theia/core/lib/common/path';
|
||||
import { LibraryServiceImpl } from './library-service-impl';
|
||||
import { examplesPath } from './resources';
|
||||
|
||||
interface BuiltInSketchRef {
|
||||
readonly name: string;
|
||||
@@ -64,7 +65,7 @@ export class BuiltInExamplesServiceImpl {
|
||||
if (this._builtIns) {
|
||||
return this._builtIns;
|
||||
}
|
||||
const examplesRootPath = join(__dirname, '..', '..', 'Examples');
|
||||
const examplesRootPath = examplesPath;
|
||||
const examplesRootUri = FileUri.create(examplesRootPath);
|
||||
const rawJson = await fs.promises.readFile(
|
||||
join(examplesRootPath, 'examples.json'),
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
import { spawn } from 'node:child_process';
|
||||
import os from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
export type ArduinoBinaryName =
|
||||
| 'arduino-cli'
|
||||
| 'arduino-fwuploader'
|
||||
| 'arduino-language-server';
|
||||
export type ClangBinaryName = 'clangd' | 'clang-format';
|
||||
export type BinaryName = ArduinoBinaryName | ClangBinaryName;
|
||||
|
||||
export function getExecPath(binaryName: BinaryName): string {
|
||||
const filename = `${binaryName}${os.platform() === 'win32' ? '.exe' : ''}`;
|
||||
return join(__dirname, '..', '..', 'build', filename);
|
||||
}
|
||||
|
||||
export function spawnCommand(
|
||||
command: string,
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { ExecutableService } from '../common/protocol/executable-service';
|
||||
import { getExecPath } from './exec-util';
|
||||
import {
|
||||
arduinoCliPath,
|
||||
arduinoLanguageServerPath,
|
||||
clangdPath,
|
||||
} from './resources';
|
||||
|
||||
@injectable()
|
||||
export class ExecutableServiceImpl implements ExecutableService {
|
||||
@@ -11,9 +15,9 @@ export class ExecutableServiceImpl implements ExecutableService {
|
||||
lsUri: string;
|
||||
}> {
|
||||
return {
|
||||
clangdUri: FileUri.create(getExecPath('clangd')).toString(),
|
||||
cliUri: FileUri.create(getExecPath('arduino-cli')).toString(),
|
||||
lsUri: FileUri.create(getExecPath('arduino-language-server')).toString(),
|
||||
clangdUri: FileUri.create(clangdPath).toString(),
|
||||
cliUri: FileUri.create(arduinoCliPath).toString(),
|
||||
lsUri: FileUri.create(arduinoLanguageServerPath).toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,46 +3,56 @@ import {
|
||||
LocalizationRegistry,
|
||||
} from '@theia/core/lib/node/i18n/localization-contribution';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { join } from 'node:path';
|
||||
import bgJson from '../resources/i18n/bg.json';
|
||||
import csJson from '../resources/i18n/cs.json';
|
||||
import deJson from '../resources/i18n/de.json';
|
||||
import esJson from '../resources/i18n/es.json';
|
||||
import frJson from '../resources/i18n/fr.json';
|
||||
import huJson from '../resources/i18n/hu.json';
|
||||
import itJson from '../resources/i18n/it.json';
|
||||
import jaJson from '../resources/i18n/ja.json';
|
||||
import koJson from '../resources/i18n/ko.json';
|
||||
import nlJson from '../resources/i18n/nl.json';
|
||||
import plJson from '../resources/i18n/pl.json';
|
||||
import ptJson from '../resources/i18n/pt.json';
|
||||
import ruJson from '../resources/i18n/ru.json';
|
||||
import trJson from '../resources/i18n/tr.json';
|
||||
import uk_UAJson from '../resources/i18n/uk_UA.json';
|
||||
import zhJson from '../resources/i18n/zh.json';
|
||||
import zh_HantJson from '../resources/i18n/zh-Hant.json';
|
||||
|
||||
@injectable()
|
||||
export class ArduinoLocalizationContribution
|
||||
implements LocalizationContribution
|
||||
{
|
||||
// 0. index: locale
|
||||
// 1. index: optional JSON file to `require` (if differs from the locale)
|
||||
// keys: locales
|
||||
// values: the required JSON modules
|
||||
// If you touch the locales, please keep the alphabetical order. Also in the `package.json` for the VS Code language packs. Thank you! ❤️
|
||||
// Note that IDE2 has more translations than available VS Code language packs. (https://github.com/arduino/arduino-ide/issues/1447)
|
||||
private readonly locales: ReadonlyArray<[string, string?]> = [
|
||||
['bg'],
|
||||
['cs'],
|
||||
['de'],
|
||||
['es'],
|
||||
['fr'],
|
||||
['hu'],
|
||||
// ['id'], Does not have Transifex translations, but has a VS Code language pack available on Open VSX.
|
||||
['it'],
|
||||
['ja'],
|
||||
['ko'],
|
||||
['nl'],
|
||||
['pl'],
|
||||
['pt-br', 'pt'],
|
||||
['ru'],
|
||||
['tr'],
|
||||
['uk', 'uk_UA'],
|
||||
['zh-cn', 'zh'],
|
||||
['zh-tw', 'zh-Hant'],
|
||||
];
|
||||
private readonly locales: Readonly<Record<string, unknown>> = {
|
||||
bg: bgJson,
|
||||
cs: csJson,
|
||||
de: deJson,
|
||||
es: esJson,
|
||||
fr: frJson,
|
||||
hu: huJson,
|
||||
// id: Does not have Transifex translations, but has a VS Code language pack available on Open VSX.
|
||||
it: itJson,
|
||||
ja: jaJson,
|
||||
ko: koJson,
|
||||
nl: nlJson,
|
||||
pl: plJson,
|
||||
'pt-br': ptJson,
|
||||
ru: [ruJson],
|
||||
tr: [trJson],
|
||||
uk: uk_UAJson,
|
||||
'zh-cn': zhJson,
|
||||
'zh-tw': zh_HantJson,
|
||||
};
|
||||
|
||||
async registerLocalizations(registry: LocalizationRegistry): Promise<void> {
|
||||
for (const [locale, jsonFilename] of this.locales) {
|
||||
registry.registerLocalizationFromRequire(
|
||||
locale,
|
||||
require(join(
|
||||
__dirname,
|
||||
`../../../build/i18n/${jsonFilename ?? locale}.json`
|
||||
))
|
||||
);
|
||||
for (const [locale, module] of Object.entries(this.locales)) {
|
||||
registry.registerLocalizationFromRequire(locale, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as fs from 'node:fs';
|
||||
import fs from 'node:fs';
|
||||
import tempDir from 'temp-dir';
|
||||
import { isWindows, isOSX } from '@theia/core/lib/common/os';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as fs from 'node:fs';
|
||||
import fs from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import {
|
||||
injectable,
|
||||
@@ -38,19 +38,21 @@ export class MonitorSettingsProviderImpl implements MonitorSettingsProvider {
|
||||
private pluggableMonitorSettingsPath: string;
|
||||
|
||||
@postConstruct()
|
||||
protected async init(): Promise<void> {
|
||||
// get the monitor settings file path
|
||||
const configDirUri = await this.envVariablesServer.getConfigDirUri();
|
||||
this.pluggableMonitorSettingsPath = join(
|
||||
FileUri.fsPath(configDirUri),
|
||||
MONITOR_SETTINGS_FILE
|
||||
);
|
||||
protected init(): void {
|
||||
(async () => {
|
||||
// get the monitor settings file path
|
||||
const configDirUri = await this.envVariablesServer.getConfigDirUri();
|
||||
this.pluggableMonitorSettingsPath = join(
|
||||
FileUri.fsPath(configDirUri),
|
||||
MONITOR_SETTINGS_FILE
|
||||
);
|
||||
|
||||
// read existing settings
|
||||
await this.readSettingsFromFS();
|
||||
// read existing settings
|
||||
await this.readSettingsFromFS();
|
||||
|
||||
// init is done, resolve the deferred and unblock any call that was waiting for it
|
||||
this.ready.resolve();
|
||||
// init is done, resolve the deferred and unblock any call that was waiting for it
|
||||
this.ready.resolve();
|
||||
})();
|
||||
}
|
||||
|
||||
async getSettings(
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import * as path from 'node:path';
|
||||
import * as express from '@theia/core/shared/express';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application';
|
||||
import express from '@theia/core/shared/express';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import path from 'node:path';
|
||||
import { arduinoPlotterWebAppPath } from '../resources';
|
||||
|
||||
@injectable()
|
||||
export class PlotterBackendContribution
|
||||
implements BackendApplicationContribution
|
||||
{
|
||||
configure(app: express.Application): void {
|
||||
const index = require.resolve(
|
||||
'arduino-serial-plotter-webapp/build/index.html'
|
||||
);
|
||||
app.use(express.static(path.join(index, '..')));
|
||||
app.use(express.static(arduinoPlotterWebAppPath));
|
||||
app.get('/plotter', (req, res) => {
|
||||
console.log(
|
||||
`Serving serial plotter on http://${req.headers.host}${req.url}`
|
||||
);
|
||||
res.sendFile(index);
|
||||
res.sendFile(path.join(arduinoPlotterWebAppPath, 'index.html'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
32
arduino-ide-extension/src/node/resources.ts
Normal file
32
arduino-ide-extension/src/node/resources.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import path from 'node:path';
|
||||
|
||||
// When running the tests, the JS files are not yet bundled by webpack.
|
||||
// Hence, the `resources` folder lookup is different.
|
||||
const testEnv = process.env.IDE2_TEST === 'true';
|
||||
const resourcesPath = path.join(
|
||||
__dirname,
|
||||
...(testEnv ? ['..', '..', 'src', 'node', 'resources'] : ['resources'])
|
||||
);
|
||||
const exe = process.platform === 'win32' ? '.exe' : '';
|
||||
|
||||
// binaries
|
||||
export const arduinoCliPath = path.join(resourcesPath, 'arduino-cli' + exe);
|
||||
export const arduinoFirmwareUploaderPath = path.join(
|
||||
resourcesPath,
|
||||
'arduino-fwuploader' + exe
|
||||
);
|
||||
export const arduinoLanguageServerPath = path.join(
|
||||
resourcesPath,
|
||||
'arduino-language-server' + exe
|
||||
);
|
||||
export const clangdPath = path.join(resourcesPath, 'clangd' + exe);
|
||||
export const clangFormatPath = path.join(resourcesPath, 'clang-format' + exe);
|
||||
|
||||
// plotter
|
||||
export const arduinoPlotterWebAppPath = path.join(
|
||||
resourcesPath,
|
||||
'arduino-serial-plotter-webapp'
|
||||
);
|
||||
|
||||
// examples
|
||||
export const examplesPath = path.join(resourcesPath, 'Examples');
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
import { FileSystemWatcherService } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
import { NsfwFileSystemWatcherServerOptions } from '@theia/filesystem/lib/node/nsfw-watcher/nsfw-filesystem-service';
|
||||
import { FileSystemWatcherServiceDispatcher } from '@theia/filesystem/lib/node/filesystem-watcher-dispatcher';
|
||||
import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-filesystem-service';
|
||||
import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-watcher/nsfw-filesystem-service';
|
||||
|
||||
export function rebindNsfwFileSystemWatcher(rebind: interfaces.Rebind): void {
|
||||
rebind<NsfwFileSystemWatcherServiceProcessOptions>(
|
||||
NsfwFileSystemWatcherServiceProcessOptions
|
||||
).toConstantValue({
|
||||
entryPoint: join(__dirname, 'index.js'),
|
||||
entryPoint: join(__dirname, 'nsfw-watcher'),
|
||||
});
|
||||
rebind<FileSystemWatcherService>(FileSystemWatcherService)
|
||||
.toDynamicValue((context) =>
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as yargs from '@theia/core/shared/yargs';
|
||||
import { JsonRpcProxyFactory } from '@theia/core';
|
||||
import { JsonRpcProxyFactory } from '@theia/core/lib/common/messaging/proxy-factory';
|
||||
import { NoDelayDisposalTimeoutNsfwFileSystemWatcherService } from './nsfw-filesystem-service';
|
||||
import type { IPCEntryPoint } from '@theia/core/lib/node/messaging/ipc-protocol';
|
||||
import type { FileSystemWatcherServiceClient } from '@theia/filesystem/lib/common/filesystem-watcher-protocol';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Emitter } from '@theia/core';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import * as WebSocket from '@theia/core/shared/ws';
|
||||
import WebSocket from '@theia/core/shared/ws';
|
||||
import { WebSocketProvider } from './web-socket-provider';
|
||||
|
||||
@injectable()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Event } from '@theia/core/lib/common/event';
|
||||
import * as WebSocket from '@theia/core/shared/ws';
|
||||
import type { AddressInfo } from '@theia/core/shared/ws';
|
||||
|
||||
export const WebSocketProvider = Symbol('WebSocketProvider');
|
||||
export interface WebSocketProvider {
|
||||
getAddress(): WebSocket.AddressInfo;
|
||||
getAddress(): AddressInfo;
|
||||
sendMessage(message: string): void;
|
||||
onMessageReceived: Event<string>;
|
||||
onClientsNumberChanged: Event<number>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import * as temp from 'temp';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import temp from 'temp';
|
||||
import { expect } from 'chai';
|
||||
import { ChildProcess } from 'node:child_process';
|
||||
import { safeLoad, safeDump } from 'js-yaml';
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { assert, expect } from 'chai';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import {
|
||||
ArduinoBinaryName,
|
||||
BinaryName,
|
||||
ClangBinaryName,
|
||||
getExecPath,
|
||||
spawnCommand,
|
||||
} from '../../node/exec-util';
|
||||
import { spawnCommand } from '../../node/exec-util';
|
||||
import temp from 'temp';
|
||||
import {
|
||||
arduinoCliPath,
|
||||
arduinoFirmwareUploaderPath,
|
||||
arduinoLanguageServerPath,
|
||||
clangdPath,
|
||||
clangFormatPath,
|
||||
} from '../../node/resources';
|
||||
|
||||
describe('exec-utils', () => {
|
||||
describe('spawnCommand', () => {
|
||||
@@ -26,7 +27,7 @@ describe('exec-utils', () => {
|
||||
|
||||
it("should execute the command without 'shell:true' even if the path contains spaces but is not escaped", async () => {
|
||||
const segment = 'with some spaces';
|
||||
const cliPath = getExecPath('arduino-cli');
|
||||
const cliPath = arduinoCliPath;
|
||||
const filename = path.basename(cliPath);
|
||||
const tempPath = tracked.mkdirSync();
|
||||
const tempPathWitSpaces = path.join(tempPath, segment);
|
||||
@@ -44,7 +45,7 @@ describe('exec-utils', () => {
|
||||
type AssertOutput = (stdout: string) => void;
|
||||
|
||||
interface GetExecPathTestSuite {
|
||||
readonly name: BinaryName;
|
||||
readonly binaryName: string;
|
||||
readonly flags?: string[];
|
||||
readonly assertOutput: AssertOutput;
|
||||
/**
|
||||
@@ -54,29 +55,29 @@ describe('exec-utils', () => {
|
||||
readonly expectNonZeroExit?: boolean;
|
||||
}
|
||||
|
||||
const binaryNameToVersionMapping: Record<BinaryName, string> = {
|
||||
'arduino-cli': 'cli',
|
||||
'arduino-language-server': 'languageServer',
|
||||
'arduino-fwuploader': 'fwuploader',
|
||||
clangd: 'clangd',
|
||||
'clang-format': 'clangd',
|
||||
const binaryNameToPathMapping: Record<string, string> = {
|
||||
'arduino-cli': arduinoCliPath,
|
||||
'arduino-language-server': arduinoLanguageServerPath,
|
||||
'arduino-fwuploader': arduinoFirmwareUploaderPath,
|
||||
clangd: clangdPath,
|
||||
'clang-format': clangFormatPath,
|
||||
};
|
||||
|
||||
function readVersionFromPackageJson(name: BinaryName): string {
|
||||
function readVersionFromPackageJson(binaryName: string): string {
|
||||
const raw = fs.readFileSync(
|
||||
path.join(__dirname, '..', '..', '..', 'package.json'),
|
||||
{ encoding: 'utf8' }
|
||||
);
|
||||
const json = JSON.parse(raw);
|
||||
expect(json.arduino).to.be.not.undefined;
|
||||
const mappedName = binaryNameToVersionMapping[name];
|
||||
expect(mappedName).to.be.not.undefined;
|
||||
const version = json.arduino[mappedName].version;
|
||||
const version =
|
||||
json.arduino[binaryName === 'clang-format' ? 'clangd' : binaryName]
|
||||
.version;
|
||||
expect(version).to.be.not.undefined;
|
||||
return version;
|
||||
}
|
||||
|
||||
function createTaskAssert(name: ArduinoBinaryName): AssertOutput {
|
||||
function createTaskAssert(name: string): AssertOutput {
|
||||
const version = readVersionFromPackageJson(name);
|
||||
if (typeof version === 'string') {
|
||||
return (stdout: string) => {
|
||||
@@ -91,7 +92,7 @@ describe('exec-utils', () => {
|
||||
};
|
||||
}
|
||||
|
||||
function createClangdAssert(name: ClangBinaryName): AssertOutput {
|
||||
function createClangdAssert(name: string): AssertOutput {
|
||||
const version = readVersionFromPackageJson(name);
|
||||
return (stdout: string) => {
|
||||
expect(stdout.includes(name)).to.be.true;
|
||||
@@ -101,17 +102,17 @@ describe('exec-utils', () => {
|
||||
|
||||
const suites: GetExecPathTestSuite[] = [
|
||||
{
|
||||
name: 'arduino-cli',
|
||||
binaryName: 'arduino-cli',
|
||||
flags: ['version'],
|
||||
assertOutput: createTaskAssert('arduino-cli'),
|
||||
},
|
||||
{
|
||||
name: 'arduino-fwuploader',
|
||||
binaryName: 'arduino-fwuploader',
|
||||
flags: ['version'],
|
||||
assertOutput: createTaskAssert('arduino-fwuploader'),
|
||||
},
|
||||
{
|
||||
name: 'arduino-language-server',
|
||||
binaryName: 'arduino-language-server',
|
||||
assertOutput: (stderr: string) => {
|
||||
expect(stderr.includes('Path to ArduinoCLI config file must be set.'))
|
||||
.to.be.true;
|
||||
@@ -119,12 +120,12 @@ describe('exec-utils', () => {
|
||||
expectNonZeroExit: true,
|
||||
},
|
||||
{
|
||||
name: 'clangd',
|
||||
binaryName: 'clangd',
|
||||
flags: ['--version'],
|
||||
assertOutput: createClangdAssert('clangd'),
|
||||
},
|
||||
{
|
||||
name: 'clang-format',
|
||||
binaryName: 'clang-format',
|
||||
flags: ['--version'],
|
||||
assertOutput: createClangdAssert('clang-format'),
|
||||
},
|
||||
@@ -133,13 +134,13 @@ describe('exec-utils', () => {
|
||||
// This is not a functional test but it ensures all executables provided by IDE2 are tested.
|
||||
it('should cover all provided executables', () => {
|
||||
expect(suites.length).to.be.equal(
|
||||
Object.keys(binaryNameToVersionMapping).length
|
||||
Object.keys(binaryNameToPathMapping).length
|
||||
);
|
||||
});
|
||||
|
||||
suites.map((suite) =>
|
||||
it(`should resolve '${suite.name}'`, async () => {
|
||||
const execPath = getExecPath(suite.name);
|
||||
it(`should resolve '${suite.binaryName}'`, async () => {
|
||||
const execPath = binaryNameToPathMapping[suite.binaryName];
|
||||
expect(execPath).to.be.not.undefined;
|
||||
expect(execPath).to.be.not.empty;
|
||||
expect(fs.accessSync(execPath, fs.constants.X_OK)).to.be.undefined;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Mutable } from '@theia/core/lib/common/types';
|
||||
import { FileUri } from '@theia/core/lib/node/file-uri';
|
||||
import stableJsonStringify from 'fast-json-stable-stringify';
|
||||
import * as assert from 'node:assert';
|
||||
import assert from 'node:assert/strict';
|
||||
import { basename, join } from 'node:path';
|
||||
import { SketchContainer, SketchRef } from '../../common/protocol';
|
||||
import { discoverSketches } from '../../node/sketches-service-impl';
|
||||
@@ -67,7 +67,7 @@ function containersDeepEquals(
|
||||
) {
|
||||
const stableActual = JSON.parse(stableJsonStringify(actual));
|
||||
const stableExpected = JSON.parse(stableJsonStringify(expected));
|
||||
assert.deepEqual(stableActual, stableExpected);
|
||||
assert.deepStrictEqual(stableActual, stableExpected); // TODO: get rid of `fast-json-stable-stringify`
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,8 +86,8 @@ function expectedTestSketchbookContainer(
|
||||
rootUri += '/';
|
||||
}
|
||||
const adjustUri = (sketch: Mutable<SketchRef>) => {
|
||||
assert.equal(sketch.uri.startsWith('template://'), true);
|
||||
assert.equal(sketch.uri.startsWith('template:///'), false);
|
||||
assert.strictEqual(sketch.uri.startsWith('template://'), true);
|
||||
assert.strictEqual(sketch.uri.startsWith('template:///'), false);
|
||||
sketch.uri = sketch.uri.replace('template://', rootUri).toString();
|
||||
return sketch;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user