From db261489454d6be2d8dc7a43b6f296143fae60f7 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 20 May 2022 12:11:23 +0200 Subject: [PATCH 01/45] Dropped Git and the custom layout restorer. Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 4 +- .../browser/arduino-ide-frontend-module.ts | 13 -- .../src/browser/theia/core/keybindings.ts | 30 ----- .../theia/core/shell-layout-restorer.ts | 56 -------- .../src/node/arduino-ide-backend-module.ts | 5 - .../src/node/theia/git/git-init.ts | 56 -------- electron/build/template-package.json | 4 +- package.json | 2 - yarn.lock | 127 +----------------- 9 files changed, 6 insertions(+), 291 deletions(-) delete mode 100644 arduino-ide-extension/src/browser/theia/core/keybindings.ts delete mode 100644 arduino-ide-extension/src/browser/theia/core/shell-layout-restorer.ts delete mode 100644 arduino-ide-extension/src/node/theia/git/git-init.ts diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 5db304aa6..3e6c4c0a6 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -28,7 +28,6 @@ "@theia/editor-preview": "1.25.0", "@theia/electron": "1.25.0", "@theia/filesystem": "1.25.0", - "@theia/git": "1.25.0", "@theia/keymaps": "1.25.0", "@theia/markers": "1.25.0", "@theia/monaco": "1.25.0", @@ -63,11 +62,10 @@ "atob": "^2.1.2", "auth0-js": "^9.14.0", "btoa": "^1.2.1", - "css-element-queries": "^1.2.0", "dateformat": "^3.0.3", "deepmerge": "2.0.1", "electron-updater": "^4.6.5", - "fuzzy": "^0.1.3", + "fast-safe-stringify": "^2.1.1", "glob": "^7.1.6", "google-protobuf": "^3.11.4", "grpc": "^1.24.11", diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 355b4e8a9..081d06d54 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -48,9 +48,7 @@ import { MonacoStatusBarContribution as TheiaMonacoStatusBarContribution } from import { MonacoStatusBarContribution } from './theia/monaco/monaco-status-bar-contribution'; import { ApplicationShell as TheiaApplicationShell, - ShellLayoutRestorer as TheiaShellLayoutRestorer, CommonFrontendContribution as TheiaCommonFrontendContribution, - KeybindingRegistry as TheiaKeybindingRegistry, TabBarRendererFactory, ContextMenuRenderer, createTreeContainer, @@ -88,7 +86,6 @@ import { TabBarDecoratorService } from './theia/core/tab-bar-decorator'; import { ProblemManager as TheiaProblemManager } from '@theia/markers/lib/browser'; import { ProblemManager } from './theia/markers/problem-manager'; import { BoardsAutoInstaller } from './boards/boards-auto-installer'; -import { ShellLayoutRestorer } from './theia/core/shell-layout-restorer'; import { EditorMode } from './editor-mode'; import { ListItemRenderer } from './widgets/component-list/list-item-renderer'; import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; @@ -138,7 +135,6 @@ import { PreferencesContribution } from './theia/preferences/preferences-contrib import { QuitApp } from './contributions/quit-app'; import { SketchControl } from './contributions/sketch-control'; import { Settings } from './contributions/settings'; -import { KeybindingRegistry } from './theia/core/keybindings'; import { WorkspaceCommandContribution } from './theia/workspace/workspace-commands'; import { WorkspaceDeleteHandler as TheiaWorkspaceDeleteHandler } from '@theia/workspace/lib/browser/workspace-delete-handler'; import { WorkspaceDeleteHandler } from './theia/workspace/workspace-delete-handler'; @@ -276,8 +272,6 @@ import { } from './dialogs/ide-updater/ide-updater-dialog'; import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-provider'; -const ElementQueries = require('css-element-queries/src/ElementQueries'); - MonacoThemingService.register({ id: 'arduino-theme', label: 'Light (Arduino)', @@ -286,8 +280,6 @@ MonacoThemingService.register({ }); export default new ContainerModule((bind, unbind, isBound, rebind) => { - ElementQueries.listen(); - ElementQueries.init(); // Commands and toolbar items bind(ArduinoFrontendContribution).toSelf().inSingletonScope(); @@ -477,7 +469,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { rebind(TheiaPreferencesContribution) .to(PreferencesContribution) .inSingletonScope(); - rebind(TheiaKeybindingRegistry).to(KeybindingRegistry).inSingletonScope(); rebind(TheiaWorkspaceCommandContribution) .to(WorkspaceCommandContribution) .inSingletonScope(); @@ -542,10 +533,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(ProblemManager).toSelf().inSingletonScope(); rebind(TheiaProblemManager).toService(ProblemManager); - // Customized layout restorer that can restore the state in async way: https://github.com/eclipse-theia/theia/issues/6579 - bind(ShellLayoutRestorer).toSelf().inSingletonScope(); - rebind(TheiaShellLayoutRestorer).toService(ShellLayoutRestorer); - // No dropdown for the _Output_ view. bind(OutputToolbarContribution).toSelf().inSingletonScope(); rebind(TheiaOutputToolbarContribution).toService(OutputToolbarContribution); diff --git a/arduino-ide-extension/src/browser/theia/core/keybindings.ts b/arduino-ide-extension/src/browser/theia/core/keybindings.ts deleted file mode 100644 index b6d55f564..000000000 --- a/arduino-ide-extension/src/browser/theia/core/keybindings.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { injectable } from '@theia/core/shared/inversify'; -import { Command } from '@theia/core/lib/common/command'; -import { Keybinding } from '@theia/core/lib/common/keybinding'; -import { - KeybindingRegistry as TheiaKeybindingRegistry, - KeybindingScope, -} from '@theia/core/lib/browser/keybinding'; - -@injectable() -export class KeybindingRegistry extends TheiaKeybindingRegistry { - // https://github.com/eclipse-theia/theia/issues/8209 - unregisterKeybinding(key: string): void; - unregisterKeybinding(keybinding: Keybinding): void; - unregisterKeybinding(command: Command): void; - unregisterKeybinding(arg: string | Keybinding | Command): void { - const keymap = this.keymaps[KeybindingScope.DEFAULT]; - const filter = Command.is(arg) - ? ({ command }: Keybinding) => command === arg.id - : ({ keybinding }: Keybinding) => - Keybinding.is(arg) - ? keybinding === arg.keybinding - : keybinding === arg; - for (const binding of keymap.filter(filter)) { - const idx = keymap.indexOf(binding); - if (idx !== -1) { - keymap.splice(idx, 1); - } - } - } -} diff --git a/arduino-ide-extension/src/browser/theia/core/shell-layout-restorer.ts b/arduino-ide-extension/src/browser/theia/core/shell-layout-restorer.ts deleted file mode 100644 index 510a1944f..000000000 --- a/arduino-ide-extension/src/browser/theia/core/shell-layout-restorer.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { injectable } from '@theia/core/shared/inversify'; -import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; -import { ShellLayoutRestorer as TheiaShellLayoutRestorer } from '@theia/core/lib/browser/shell/shell-layout-restorer'; - -@injectable() -export class ShellLayoutRestorer extends TheiaShellLayoutRestorer { - // Workaround for https://github.com/eclipse-theia/theia/issues/6579. - async storeLayoutAsync(app: FrontendApplication): Promise { - if (this.shouldStoreLayout) { - try { - this.logger.info('>>> Storing the layout...'); - const layoutData = app.shell.getLayoutData(); - const serializedLayoutData = this.deflate(layoutData); - await this.storageService.setData( - this.storageKey, - serializedLayoutData - ); - this.logger.info('<<< The layout has been successfully stored.'); - } catch (error) { - await this.storageService.setData(this.storageKey, undefined); - this.logger.error('Error during serialization of layout data', error); - } - } - } - - async restoreLayout(app: FrontendApplication): Promise { - this.logger.info('>>> Restoring the layout state...'); - const serializedLayoutData = await this.storageService.getData( - this.storageKey - ); - if (serializedLayoutData === undefined) { - this.logger.info('<<< Nothing to restore.'); - return false; - } - - const layoutData = await this.inflate(serializedLayoutData); - // workaround to remove duplicated tabs - const filesUri: string[] = []; - if ((layoutData as any)?.mainPanel?.main?.widgets) { - (layoutData as any).mainPanel.main.widgets = ( - layoutData as any - ).mainPanel.main.widgets.filter((widget: any) => { - const uri = widget.getResourceUri().toString(); - if (filesUri.includes(uri)) { - return false; - } - filesUri.push(uri); - return true; - }); - } - - await app.shell.setLayoutData(layoutData); - this.logger.info('<<< The layout has been successfully restored.'); - return true; - } -} diff --git a/arduino-ide-extension/src/node/arduino-ide-backend-module.ts b/arduino-ide-extension/src/node/arduino-ide-backend-module.ts index 826c41e60..23ae3a083 100644 --- a/arduino-ide-extension/src/node/arduino-ide-backend-module.ts +++ b/arduino-ide-extension/src/node/arduino-ide-backend-module.ts @@ -80,8 +80,6 @@ import { } from '../common/protocol'; import { BackendApplication } from './theia/core/backend-application'; import { BoardDiscovery } from './board-discovery'; -import { DefaultGitInit } from './theia/git/git-init'; -import { GitInit } from '@theia/git/lib/node/init/git-init'; import { AuthenticationServiceImpl } from './auth/authentication-service-impl'; import { AuthenticationService, @@ -316,9 +314,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { .inSingletonScope() .whenTargetNamed(SerialServiceName); - bind(DefaultGitInit).toSelf(); - rebind(GitInit).toService(DefaultGitInit); - // Remote sketchbook bindings bind(AuthenticationServiceImpl).toSelf().inSingletonScope(); bind(AuthenticationService).toService(AuthenticationServiceImpl); diff --git a/arduino-ide-extension/src/node/theia/git/git-init.ts b/arduino-ide-extension/src/node/theia/git/git-init.ts deleted file mode 100644 index 56bcc02f1..000000000 --- a/arduino-ide-extension/src/node/theia/git/git-init.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { injectable } from '@theia/core/shared/inversify'; -import findGit from 'find-git-exec'; -import { dirname } from 'path'; -import { pathExists } from 'fs-extra'; -import { GitInit } from '@theia/git/lib/node/init/git-init'; -import { DisposableCollection } from '@theia/core/lib/common/disposable'; - -@injectable() -export class DefaultGitInit implements GitInit { - protected readonly toDispose = new DisposableCollection(); - - async init(): Promise { - const { env } = process; - try { - const { execPath, path, version } = await findGit(); - if (!!execPath && !!path && !!version) { - const dir = dirname(dirname(path)); - const [execPathOk, pathOk, dirOk] = await Promise.all([ - pathExists(execPath), - pathExists(path), - pathExists(dir), - ]); - if (execPathOk && pathOk && dirOk) { - if ( - typeof env.LOCAL_GIT_DIRECTORY !== 'undefined' && - env.LOCAL_GIT_DIRECTORY !== dir - ) { - console.error( - `Misconfigured env.LOCAL_GIT_DIRECTORY: ${env.LOCAL_GIT_DIRECTORY}. dir was: ${dir}` - ); - return; - } - if ( - typeof env.GIT_EXEC_PATH !== 'undefined' && - env.GIT_EXEC_PATH !== execPath - ) { - console.error( - `Misconfigured env.GIT_EXEC_PATH: ${env.GIT_EXEC_PATH}. execPath was: ${execPath}` - ); - return; - } - process.env.LOCAL_GIT_DIRECTORY = dir; - process.env.GIT_EXEC_PATH = execPath; - console.info(`Using Git [${version}] from the PATH. (${path})`); - return; - } - } - } catch (err) { - console.error(err); - } - } - - dispose(): void { - this.toDispose.dispose(); - } -} diff --git a/electron/build/template-package.json b/electron/build/template-package.json index 3100d1e89..caa8087cd 100644 --- a/electron/build/template-package.json +++ b/electron/build/template-package.json @@ -3,9 +3,7 @@ "author": "Arduino SA", "resolutions": { "**/fs-extra": "^4.0.3", - "electron-builder": "23.0.2", - "find-git-exec": "0.0.4", - "dugite-extra": "0.1.15" + "electron-builder": "23.0.2" }, "dependencies": { "node-log-rotate": "^0.1.5" diff --git a/package.json b/package.json index 5ad471310..8f974b80d 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,6 @@ "jsdom": "^11.5.1" }, "resolutions": { - "find-git-exec": "0.0.4", - "dugite-extra": "0.1.15", "@types/react": "16.14.25" }, "scripts": { diff --git a/yarn.lock b/yarn.lock index 1ca796316..212d2689c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2638,30 +2638,6 @@ uuid "^8.0.0" vscode-languageserver-textdocument "^1.0.1" -"@theia/git@1.25.0": - version "1.25.0" - resolved "https://registry.yarnpkg.com/@theia/git/-/git-1.25.0.tgz#f1c028d7432ebca8622e296aa1139bcb7fe9fd4d" - integrity sha512-UB/m2vt+WEJZS81PZ2aOXbIDSVNtith/V3o8H41XcxZ25dYwbpC0F6Ln4br15vGOASGBKFPzAwBeNXDyEAOZkw== - dependencies: - "@theia/core" "1.25.0" - "@theia/editor" "1.25.0" - "@theia/filesystem" "1.25.0" - "@theia/monaco-editor-core" "1.65.2" - "@theia/navigator" "1.25.0" - "@theia/scm" "1.25.0" - "@theia/scm-extra" "1.25.0" - "@theia/workspace" "1.25.0" - "@types/diff" "^3.2.2" - "@types/p-queue" "^2.3.1" - diff "^3.4.0" - dugite-extra "0.1.15" - find-git-exec "^0.0.4" - find-git-repositories "^0.1.1" - moment "2.29.2" - octicons "^7.1.0" - p-queue "^2.4.2" - ts-md5 "^1.2.2" - "@theia/keymaps@1.25.0": version "1.25.0" resolved "https://registry.yarnpkg.com/@theia/keymaps/-/keymaps-1.25.0.tgz#0adfb6f088a532aa3c2f05448ac5697e6a16f5ad" @@ -2860,17 +2836,6 @@ node-pty "0.11.0-beta17" string-argv "^0.1.1" -"@theia/scm-extra@1.25.0": - version "1.25.0" - resolved "https://registry.yarnpkg.com/@theia/scm-extra/-/scm-extra-1.25.0.tgz#0ab22c77ef5918e35c44c3750fb46202fad26cbd" - integrity sha512-n4slV6Reb/zjtf9gZCs0l9pFmixi5gY+ut0Du1ZN4sqGJvSF5bfEx6567CbqX1zitsMTr2/dSLReS/Rqsu8flg== - dependencies: - "@theia/core" "1.25.0" - "@theia/editor" "1.25.0" - "@theia/filesystem" "1.25.0" - "@theia/navigator" "1.25.0" - "@theia/scm" "1.25.0" - "@theia/scm@1.25.0": version "1.25.0" resolved "https://registry.yarnpkg.com/@theia/scm/-/scm-1.25.0.tgz#e9765fc09979508b77bcfecd28dda8d8c4e6c8b0" @@ -3351,11 +3316,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.34.tgz#3b0b6a50ff797280b8d000c6281d229f9c538cef" integrity sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA== -"@types/node@^10.14.22": - version "10.17.60" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" - integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== - "@types/node@^14.6.2": version "14.18.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.18.tgz#5c9503030df484ccffcbb935ea9a9e1d6fad1a20" @@ -3591,7 +3551,7 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-7.0.5.tgz#b1d2f772142a301538fae9bdf9cf15b9f2573a29" integrity sha512-hKB88y3YHL8oPOs/CNlaXtjWn93+Bs48sDQR37ZUqG2tLeCS7EA1cmnkKsuQsub9OKEB/y/Rw9zqJqqNSbqVlQ== -"@types/which@^1.3.1", "@types/which@^1.3.2": +"@types/which@^1.3.1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf" integrity sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA== @@ -5269,13 +5229,6 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -checksum@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/checksum/-/checksum-0.1.1.tgz#dc6527d4c90be8560dbd1ed4cecf3297d528e9e9" - integrity sha512-xWkkJpoWQ6CptWw2GvtoQbScL3xtvGjoqvHpALE7B0tSHxSw0ex0tlsKOKkbETaOYGBhMliAyscestDyAZIN9g== - dependencies: - optimist "~0.3.5" - chokidar@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" @@ -5940,11 +5893,6 @@ crypto-js@^4.1.1: resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== -css-element-queries@^1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/css-element-queries/-/css-element-queries-1.2.3.tgz#e14940b1fcd4bf0da60ea4145d05742d7172e516" - integrity sha512-QK9uovYmKTsV2GXWQiMOByVNrLn2qz6m3P7vWpOR4IdD6I3iXoDw5qtgJEN3Xq7gIbdHVKvzHjdAtcl+4Arc4Q== - css-loader@^6.2.0: version "6.7.1" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.1.tgz#e98106f154f6e1baf3fc3bc455cb9981c1d5fd2e" @@ -6453,28 +6401,6 @@ drivelist@^9.0.2: nan "^2.14.0" prebuild-install "^5.2.4" -dugite-extra@0.1.15: - version "0.1.15" - resolved "https://registry.yarnpkg.com/dugite-extra/-/dugite-extra-0.1.15.tgz#322406b628ea5515c5c6fcd65e4d040543d6268a" - integrity sha512-beLmQcIXLA8aXqWQZF/ooECoZvYKpBywIFwgqAoYnV04NdWUXDtZ6mMcjQf5eAz5PjXGXAYSuQ31zkPL8J85+A== - dependencies: - byline "^5.0.0" - dugite-no-gpl "1.69.0" - find-git-exec "^0.0.4" - upath "^2.0.1" - -dugite-no-gpl@1.69.0: - version "1.69.0" - resolved "https://registry.yarnpkg.com/dugite-no-gpl/-/dugite-no-gpl-1.69.0.tgz#bc9007cf5a595180f563ccc0e4f2cc80ebbaa52e" - integrity sha512-9NzPMyWW1uWEm+rEGivfQ0+zZ9soXrtk/zb6FIVpPa5CLoUdhMkLY4jHc0DDyayarxivJgrI/rHDdTUej4Zhrw== - dependencies: - checksum "^0.1.1" - mkdirp "^0.5.1" - progress "^2.0.0" - request "^2.86.0" - rimraf "^2.5.4" - tar "^4.0.2" - duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -7247,7 +7173,7 @@ fast-plist@^0.1.2: resolved "https://registry.yarnpkg.com/fast-plist/-/fast-plist-0.1.2.tgz#a45aff345196006d406ca6cdcd05f69051ef35b8" integrity sha1-pFr/NFGWAG1AbKbNzQX2kFHvNbg= -fast-safe-stringify@^2.0.7: +fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== @@ -7392,22 +7318,6 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-git-exec@0.0.4, find-git-exec@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/find-git-exec/-/find-git-exec-0.0.4.tgz#f1d0d35f93ad99bc81aacd357388d00ae902bc92" - integrity sha512-klzQwno+dpdeahtHhvZZ5Yn6K+zme1Aj+YJ4ZD+DywSLrQoyCywTrsubUZa1hHRehmfwBThoeKjS7fsaxhpfNA== - dependencies: - "@types/node" "^10.14.22" - "@types/which" "^1.3.2" - which "^2.0.1" - -find-git-repositories@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/find-git-repositories/-/find-git-repositories-0.1.3.tgz#4e83e085b20cb3e393c1e091adc3a3eec50b6dda" - integrity sha512-6q8ZIQ7loe0eWbz1O79J0gQ2wVpQ1ajsjV64HC2iJ7gOOqlEuDlG/T0xYr5gDYBFSHlS8dah1KGbndiWWdJ0PA== - dependencies: - nan "^2.14.0" - find-root@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" @@ -10786,11 +10696,6 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -moment@2.29.2: - version "2.29.2" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.2.tgz#00910c60b20843bcba52d37d58c628b47b1f20e4" - integrity sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg== - moment@^2.18.1, moment@^2.24.0: version "2.29.3" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.3.tgz#edd47411c322413999f7a5940d526de183c031f3" @@ -11420,13 +11325,6 @@ object.values@^1.1.5: define-properties "^1.1.3" es-abstract "^1.19.1" -octicons@^7.1.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/octicons/-/octicons-7.4.0.tgz#0be0082ed75b81e680800ef978bf47078b670091" - integrity sha512-j53BDX+FpJ4DQwENARbk9hHkwG/Oaq5NPUMNzYdGxRA/R5M6BbPVQEakUVMNKLzvzPue/gEEUTtSj6utFse5QQ== - dependencies: - object-assign "^4.1.1" - octokit-pagination-methods@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" @@ -11483,13 +11381,6 @@ open@^8.0.6: is-docker "^2.1.1" is-wsl "^2.2.0" -optimist@~0.3.5: - version "0.3.7" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" - integrity sha1-yQlBrVnkJzMokjB00s8ufLxuwNk= - dependencies: - wordwrap "~0.0.2" - optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -12975,7 +12866,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.82.0, request@^2.86.0, request@^2.87.0, request@^2.88.0: +request@^2.82.0, request@^2.87.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -14274,7 +14165,7 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^4.0.0, tar@^4.0.2, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: +tar@^4.0.0, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== @@ -14947,11 +14838,6 @@ upath@^1.1.2, upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -upath@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" - integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -15397,11 +15283,6 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - worker-loader@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-3.0.8.tgz#5fc5cda4a3d3163d9c274a4e3a811ce8b60dbb37" From 5da4b1aa7e92771bbe60078bbe0eb0256767d4b9 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 20 May 2022 12:11:39 +0200 Subject: [PATCH 02/45] duration decorator. Signed-off-by: Akos Kitta --- .../src/common/decorators.ts | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 arduino-ide-extension/src/common/decorators.ts diff --git a/arduino-ide-extension/src/common/decorators.ts b/arduino-ide-extension/src/common/decorators.ts new file mode 100644 index 000000000..f02fb83d0 --- /dev/null +++ b/arduino-ide-extension/src/common/decorators.ts @@ -0,0 +1,64 @@ +import type { CancellationToken } from '@theia/core/lib/common/cancellation'; +import { default as stringifySafe } from 'fast-safe-stringify'; + +export interface DurationOptions { + /** + * If not specified, falls back to the `String()` value of the `PropertyKey`. + */ + name?: string; + + /** + * If the duration exceeds this timeout (in millis), then the duration will be logged as an error. + */ + timeout?: number; +} + +export function duration(options?: DurationOptions) { + return ( + _target: unknown, + key: PropertyKey, + descriptor: PropertyDescriptor + ): PropertyDescriptor => { + const original = descriptor.value; + descriptor.value = async function (...args: unknown[]) { + const input = args + .filter((arg) => !Boolean(isCancellationToken(arg))) + .map(stringify) + .join(','); + const start = performance.now(); + const result = await original.apply(this, args); + const end = performance.now(); + const duration = end - start; + const slow = duration > (options?.timeout ?? 100); + const message = `---- ${slow ? '!!!SLOW!!! ' : ''}DURATION: ${ + options?.name ?? String(key) + } took ${duration.toFixed(3)} ms. Args: [${input}] ----`; + if (slow) { + console.error(message); + } else { + console.info(message); + } + return result; + }; + return descriptor; + }; +} + +function stringify(arg: unknown): string { + try { + return JSON.stringify(arg); + } catch { + return stringifySafe(arg); + } +} + +// The cancellation token is implicitly the last arg of the JSON-RPC invocation. We want to filter it out from the logs. +// See: https://github.com/eclipse-theia/theia/issues/10129 +function isCancellationToken(arg: unknown): arg is CancellationToken { + return ( + typeof arg === 'object' && + arg !== null && + 'onCancellationRequested' in arg && + 'isCancellationRequested' in arg + ); +} From 986d5978414ced6c65e0ed1837e278cec8c08ce7 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 20 May 2022 12:11:54 +0200 Subject: [PATCH 03/45] get ws root withot check. Signed-off-by: Akos Kitta --- .../theia/workspace/workspace-service.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 958ae0a6f..6adbe5a67 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -7,6 +7,7 @@ import { MessageService } from '@theia/core/lib/common/message-service'; import { ApplicationServer } from '@theia/core/lib/common/application-protocol'; import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; import { FocusTracker, Widget } from '@theia/core/lib/browser'; +import { DEFAULT_WINDOW_HASH } from '@theia/core/lib/common/window'; import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; import { WorkspaceService as TheiaWorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; import { ConfigService } from '../../../common/protocol/config-service'; @@ -61,6 +62,30 @@ export class WorkspaceService extends TheiaWorkspaceService { this.onCurrentWidgetChange({ newValue, oldValue: null }); } + // Was copied from the Theia implementation. + // Unlike the default behavior, IDE2 does not check the existence of the workspace before open. + protected async doGetDefaultWorkspaceUri(): Promise { + // If an empty window is explicitly requested do not restore a previous workspace. + // Note: `window.location.hash` includes leading "#" if non-empty. + if (window.location.hash === `#${DEFAULT_WINDOW_HASH}`) { + window.location.hash = ''; + return undefined; + } + + // Prefer the workspace path specified as the URL fragment, if present. + if (window.location.hash.length > 1) { + // Remove the leading # and decode the URI. + const wpPath = decodeURI(window.location.hash.substring(1)); + const workspaceUri = new URI().withPath(wpPath).withScheme('file'); + // Customization! Here, we do no check if the workspace exists. + return workspaceUri.toString(); + } else { + // Else, ask the server for its suggested workspace (usually the one + // specified on the CLI, or the most recent). + return this.server.getMostRecentlyUsedWorkspace(); + } + } + protected getDefaultWorkspaceUri(): Promise { if (this.workspaceUri) { // Avoid creating a new sketch twice From 8c95086978721dd829588977ac91895e430862b2 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 20 May 2022 13:49:39 +0200 Subject: [PATCH 04/45] Enabled `noImplicitOverride` TS option. Signed-off-by: Akos Kitta --- .../boards/boards-config-dialog-widget.tsx | 2 +- .../browser/boards/boards-config-dialog.ts | 14 +-- .../src/browser/boards/boards-config.tsx | 10 +- .../src/browser/boards/boards-list-widget.ts | 6 +- .../browser/boards/boards-toolbar-item.tsx | 8 +- .../boards-widget-frontend-contribution.ts | 2 +- .../src/browser/contributions/about.ts | 4 +- .../src/browser/contributions/add-file.ts | 4 +- .../browser/contributions/add-zip-library.ts | 4 +- .../browser/contributions/archive-sketch.ts | 4 +- .../browser/contributions/board-selection.ts | 4 +- .../browser/contributions/burn-bootloader.ts | 6 +- .../src/browser/contributions/close.ts | 10 +- .../src/browser/contributions/debug.ts | 6 +- .../contributions/edit-contributions.ts | 6 +- .../src/browser/contributions/examples.ts | 8 +- .../src/browser/contributions/help.ts | 6 +- .../browser/contributions/include-library.ts | 8 +- .../src/browser/contributions/new-sketch.ts | 8 +- .../contributions/open-recent-sketch.ts | 4 +- .../contributions/open-sketch-external.ts | 6 +- .../src/browser/contributions/open-sketch.ts | 8 +- .../src/browser/contributions/quit-app.ts | 6 +- .../browser/contributions/save-as-sketch.ts | 8 +- .../src/browser/contributions/save-sketch.ts | 8 +- .../src/browser/contributions/settings.ts | 6 +- .../browser/contributions/sketch-control.ts | 10 +- .../src/browser/contributions/sketchbook.ts | 10 +- .../contributions/upload-certificate.ts | 4 +- .../browser/contributions/upload-firmware.ts | 4 +- .../browser/contributions/upload-sketch.ts | 8 +- .../browser/contributions/verify-sketch.ts | 8 +- .../src/browser/create/create-api.ts | 4 +- .../certificate-uploader-dialog.tsx | 12 +- .../dialogs/cloud-share-sketch-dialog.tsx | 8 +- .../dialogs/do-not-ask-again-dialog.ts | 6 +- .../firmware-uploader-dialog.tsx | 14 +-- .../ide-updater/ide-updater-dialog.tsx | 14 +-- .../dialogs/settings/settings-component.tsx | 8 +- .../dialogs/settings/settings-dialog.tsx | 16 +-- .../user-fields/user-fields-dialog.tsx | 12 +- .../browser/library/library-list-widget.ts | 10 +- .../library-widget-frontend-contribution.ts | 2 +- .../monitor/monitor-view-contribution.tsx | 4 +- .../browser/serial/monitor/monitor-widget.tsx | 12 +- .../monitor/serial-monitor-send-input.tsx | 6 +- .../monitor/serial-monitor-send-output.tsx | 8 +- .../plotter/plotter-frontend-contribution.ts | 6 +- .../browser/theia/core/application-shell.ts | 12 +- .../theia/core/browser-main-menu-factory.ts | 4 +- .../browser/theia/core/browser-menu-plugin.ts | 2 +- .../core/common-frontend-contribution.ts | 4 +- .../theia/core/connection-status-service.ts | 6 +- .../theia/core/frontend-application.ts | 6 +- .../browser/theia/core/tab-bar-decorator.ts | 2 +- .../browser/theia/core/tab-bar-toolbar.tsx | 2 +- .../src/browser/theia/core/tab-bars.ts | 2 +- .../debug/debug-configuration-manager.ts | 4 +- .../theia/debug/debug-configuration-model.ts | 6 +- ...debug-frontend-application-contribution.ts | 2 +- .../browser/theia/debug/debug-hover-source.ts | 21 ---- .../browser/theia/debug/debug-hover-widget.ts | 119 ------------------ .../theia/debug/debug-session-manager.ts | 4 +- .../src/browser/theia/dialogs/dialogs.ts | 2 +- .../browser/theia/editor/editor-command.ts | 2 +- .../theia/editor/editor-widget-factory.ts | 4 +- .../keymaps/keymaps-frontend-contribution.ts | 2 +- .../theia/markers/problem-contribution.ts | 6 +- .../browser/theia/markers/problem-manager.ts | 4 +- .../notification-center-component.tsx | 2 +- .../theia/messages/notification-component.tsx | 2 +- .../notification-toasts-component.tsx | 2 +- .../theia/messages/notifications-manager.ts | 4 +- .../theia/messages/notifications-renderer.tsx | 2 +- .../theia/monaco/monaco-editor-provider.ts | 2 +- .../monaco/monaco-status-bar-contribution.ts | 4 +- .../theia/monaco/monaco-text-model-service.ts | 18 +-- .../theia/navigator/navigator-contribution.ts | 14 +-- .../navigator/navigator-tab-bar-decorator.ts | 4 +- .../theia/outline/outline-contribution.ts | 2 +- .../browser/theia/output/output-channel.ts | 4 +- .../output/output-toolbar-contribution.ts | 2 +- .../src/browser/theia/output/output-widget.ts | 2 +- .../output-channel-registry-main.ts | 12 +- .../preferences/preferences-contribution.ts | 4 +- .../src/browser/theia/scm/scm-contribution.ts | 4 +- .../search-in-workspace-factory.ts | 2 +- ...arch-in-workspace-frontend-contribution.ts | 4 +- .../search-in-workspace-result-tree-widget.ts | 2 +- .../search-in-workspace-widget.tsx | 4 +- .../theia/workspace/workspace-commands.ts | 4 +- .../workspace/workspace-delete-handler.ts | 2 +- .../workspace-frontend-contribution.ts | 8 +- .../theia/workspace/workspace-input-dialog.ts | 10 +- .../theia/workspace/workspace-service.ts | 12 +- .../workspace-variable-contribution.ts | 4 +- .../toolbar/arduino-toolbar-contribution.ts | 2 +- .../src/browser/toolbar/arduino-toolbar.tsx | 2 +- .../src/browser/widgets/arduino-select.tsx | 2 +- .../cloud-sketchbook-composite-widget.tsx | 4 +- .../cloud-sketchbook-contributions.ts | 4 +- .../cloud-sketchbook-tree-model.ts | 12 +- .../cloud-sketchbook-tree-widget.tsx | 16 +-- .../cloud-sketchbook/cloud-sketchbook-tree.ts | 20 +-- .../cloud-sketchbook-widget.ts | 8 +- .../cloud-sketchbook/cloud-user-status.tsx | 6 +- .../component-list/component-list-item.tsx | 2 +- .../widgets/component-list/component-list.tsx | 4 +- .../filterable-list-container.tsx | 6 +- .../list-widget-frontend-contribution.ts | 2 +- .../widgets/component-list/list-widget.tsx | 8 +- .../widgets/component-list/search-bar.tsx | 2 +- .../sketchbook/sketchbook-tree-model.ts | 14 +-- .../sketchbook/sketchbook-tree-widget.tsx | 20 +-- .../widgets/sketchbook/sketchbook-tree.ts | 2 +- .../sketchbook-widget-contribution.ts | 4 +- .../widgets/sketchbook/sketchbook-widget.tsx | 8 +- .../electron-window-service.ts | 2 +- .../theia/core/electron-main-menu-factory.ts | 10 +- .../theia/core/electron-menu-contribution.ts | 8 +- .../theia/electron-main-application.ts | 18 +-- .../theia/electron-main-window-service.ts | 4 +- .../src/node/core-client-provider.ts | 4 +- .../node/theia/core/backend-application.ts | 4 +- .../env-variables/env-variables-server.ts | 2 +- .../workspace/default-workspace-server.ts | 2 +- .../src/test/node/arduino-daemon-impl.test.ts | 6 +- arduino-ide-extension/tsconfig.json | 1 + 128 files changed, 388 insertions(+), 525 deletions(-) delete mode 100644 arduino-ide-extension/src/browser/theia/debug/debug-hover-source.ts delete mode 100644 arduino-ide-extension/src/browser/theia/debug/debug-hover-widget.ts diff --git a/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx b/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx index 80cbf49fe..a21066bd1 100644 --- a/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx +++ b/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx @@ -60,7 +60,7 @@ export class BoardsConfigDialogWidget extends ReactWidget { ); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); if (this.focusNode instanceof HTMLInputElement) { this.focusNode.select(); diff --git a/arduino-ide-extension/src/browser/boards/boards-config-dialog.ts b/arduino-ide-extension/src/browser/boards/boards-config-dialog.ts index 8bf143ab2..d5db717c8 100644 --- a/arduino-ide-extension/src/browser/boards/boards-config-dialog.ts +++ b/arduino-ide-extension/src/browser/boards/boards-config-dialog.ts @@ -26,7 +26,7 @@ export class BoardsConfigDialog extends AbstractDialog { constructor( @inject(BoardsConfigDialogProps) - protected readonly props: BoardsConfigDialogProps + protected override readonly props: BoardsConfigDialogProps ) { super(props); @@ -52,7 +52,7 @@ export class BoardsConfigDialog extends AbstractDialog { /** * Pass in an empty string if you want to reset the search term. Using `undefined` has no effect. */ - async open( + override async open( query: string | undefined = undefined ): Promise { if (typeof query === 'string') { @@ -95,7 +95,7 @@ export class BoardsConfigDialog extends AbstractDialog { return head; } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { if (this.widget.isAttached) { Widget.detach(this.widget); } @@ -110,23 +110,23 @@ export class BoardsConfigDialog extends AbstractDialog { this.update(); } - protected onUpdateRequest(msg: Message) { + protected override onUpdateRequest(msg: Message): void { super.onUpdateRequest(msg); this.widget.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); this.widget.activate(); } - protected handleEnter(event: KeyboardEvent): boolean | void { + protected override handleEnter(event: KeyboardEvent): boolean | void { if (event.target instanceof HTMLTextAreaElement) { return false; } } - protected isValid(value: BoardsConfig.Config): DialogError { + protected override isValid(value: BoardsConfig.Config): DialogError { if (!value.selectedBoard) { if (value.selectedPort) { return nls.localize( diff --git a/arduino-ide-extension/src/browser/boards/boards-config.tsx b/arduino-ide-extension/src/browser/boards/boards-config.tsx index cd8ae9110..c0a552221 100644 --- a/arduino-ide-extension/src/browser/boards/boards-config.tsx +++ b/arduino-ide-extension/src/browser/boards/boards-config.tsx @@ -47,7 +47,7 @@ export abstract class Item extends React.Component<{ missing?: boolean; details?: string; }> { - render(): React.ReactNode { + override render(): React.ReactNode { const { selected, label, missing, details } = this.props; const classNames = ['item']; if (selected) { @@ -99,7 +99,7 @@ export class BoardsConfig extends React.Component< }; } - componentDidMount() { + override componentDidMount() { this.updateBoards(); this.updatePorts( this.props.boardsServiceProvider.availableBoards @@ -141,11 +141,11 @@ export class BoardsConfig extends React.Component< ]); } - componentWillUnmount(): void { + override componentWillUnmount(): void { this.toDispose.dispose(); } - protected fireConfigChanged() { + protected fireConfigChanged(): void { const { selectedBoard, selectedPort } = this.state; this.props.onConfigChange({ selectedBoard, selectedPort }); } @@ -250,7 +250,7 @@ export class BoardsConfig extends React.Component< this.props.onFocusNodeSet(element || undefined); }; - render(): React.ReactNode { + override render(): React.ReactNode { return (
{this.renderContainer('boards', this.renderBoards.bind(this))} diff --git a/arduino-ide-extension/src/browser/boards/boards-list-widget.ts b/arduino-ide-extension/src/browser/boards/boards-list-widget.ts index da8a03875..ca2508fb9 100644 --- a/arduino-ide-extension/src/browser/boards/boards-list-widget.ts +++ b/arduino-ide-extension/src/browser/boards/boards-list-widget.ts @@ -30,7 +30,7 @@ export class BoardsListWidget extends ListWidget { } @postConstruct() - protected init(): void { + protected override init(): void { super.init(); this.toDispose.pushAll([ this.notificationCenter.onPlatformInstalled(() => @@ -42,7 +42,7 @@ export class BoardsListWidget extends ListWidget { ]); } - protected async install({ + protected override async install({ item, progressId, version, @@ -63,7 +63,7 @@ export class BoardsListWidget extends ListWidget { ); } - protected async uninstall({ + protected override async uninstall({ item, progressId, }: { diff --git a/arduino-ide-extension/src/browser/boards/boards-toolbar-item.tsx b/arduino-ide-extension/src/browser/boards/boards-toolbar-item.tsx index b94e2a620..cc7cd24da 100644 --- a/arduino-ide-extension/src/browser/boards/boards-toolbar-item.tsx +++ b/arduino-ide-extension/src/browser/boards/boards-toolbar-item.tsx @@ -41,7 +41,7 @@ export class BoardsDropDown extends React.Component { } } - render(): React.ReactNode { + override render(): React.ReactNode { return ReactDOM.createPortal(this.renderNode(), this.dropdownElement); } @@ -130,13 +130,13 @@ export class BoardsToolBarItem extends React.Component< }); } - componentDidMount() { + override componentDidMount(): void { this.props.boardsServiceClient.onAvailableBoardsChanged((availableBoards) => this.setState({ availableBoards }) ); } - componentWillUnmount(): void { + override componentWillUnmount(): void { this.toDispose.dispose(); } @@ -161,7 +161,7 @@ export class BoardsToolBarItem extends React.Component< event.nativeEvent.stopImmediatePropagation(); }; - render(): React.ReactNode { + override render(): React.ReactNode { const { coords, availableBoards } = this.state; const boardsConfig = this.props.boardsServiceClient.boardsConfig; const title = BoardsConfig.Config.toString(boardsConfig, { diff --git a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts index 815148714..af31aff6e 100644 --- a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts @@ -18,7 +18,7 @@ export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendCont }); } - async initializeLayout(): Promise { + override async initializeLayout(): Promise { this.openView(); } } diff --git a/arduino-ide-extension/src/browser/contributions/about.ts b/arduino-ide-extension/src/browser/contributions/about.ts index 761352e55..f3a50fc54 100644 --- a/arduino-ide-extension/src/browser/contributions/about.ts +++ b/arduino-ide-extension/src/browser/contributions/about.ts @@ -22,13 +22,13 @@ export class About extends Contribution { @inject(ConfigService) protected readonly configService: ConfigService; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(About.Commands.ABOUT_APP, { execute: () => this.showAbout(), }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.HELP__ABOUT_GROUP, { commandId: About.Commands.ABOUT_APP.id, label: nls.localize( diff --git a/arduino-ide-extension/src/browser/contributions/add-file.ts b/arduino-ide-extension/src/browser/contributions/add-file.ts index a6abaf78b..4285ec08a 100644 --- a/arduino-ide-extension/src/browser/contributions/add-file.ts +++ b/arduino-ide-extension/src/browser/contributions/add-file.ts @@ -16,13 +16,13 @@ export class AddFile extends SketchContribution { @inject(FileDialogService) protected readonly fileDialogService: FileDialogService; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(AddFile.Commands.ADD_FILE, { execute: () => this.addFile(), }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.SKETCH__UTILS_GROUP, { commandId: AddFile.Commands.ADD_FILE.id, label: nls.localize('arduino/contributions/addFile', 'Add File') + '...', diff --git a/arduino-ide-extension/src/browser/contributions/add-zip-library.ts b/arduino-ide-extension/src/browser/contributions/add-zip-library.ts index d3f9a6e93..927af4868 100644 --- a/arduino-ide-extension/src/browser/contributions/add-zip-library.ts +++ b/arduino-ide-extension/src/browser/contributions/add-zip-library.ts @@ -28,13 +28,13 @@ export class AddZipLibrary extends SketchContribution { @inject(LibraryService) protected readonly libraryService: LibraryService; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(AddZipLibrary.Commands.ADD_ZIP_LIBRARY, { execute: () => this.addZipLibrary(), }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { const includeLibMenuPath = [ ...ArduinoMenus.SKETCH__UTILS_GROUP, '0_include', diff --git a/arduino-ide-extension/src/browser/contributions/archive-sketch.ts b/arduino-ide-extension/src/browser/contributions/archive-sketch.ts index 698264fe7..bf7e09e7e 100644 --- a/arduino-ide-extension/src/browser/contributions/archive-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/archive-sketch.ts @@ -13,13 +13,13 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class ArchiveSketch extends SketchContribution { - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(ArchiveSketch.Commands.ARCHIVE_SKETCH, { execute: () => this.archiveSketch(), }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, { commandId: ArchiveSketch.Commands.ARCHIVE_SKETCH.id, label: nls.localize('arduino/sketch/archiveSketch', 'Archive Sketch'), diff --git a/arduino-ide-extension/src/browser/contributions/board-selection.ts b/arduino-ide-extension/src/browser/contributions/board-selection.ts index 0a4669955..b1b0bb860 100644 --- a/arduino-ide-extension/src/browser/contributions/board-selection.ts +++ b/arduino-ide-extension/src/browser/contributions/board-selection.ts @@ -47,7 +47,7 @@ export class BoardSelection extends SketchContribution { protected readonly toDisposeBeforeMenuRebuild = new DisposableCollection(); - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(BoardSelection.Commands.GET_BOARD_INFO, { execute: async () => { const { selectedBoard, selectedPort } = @@ -100,7 +100,7 @@ PID: ${PID}`; }); } - onStart(): void { + override onStart(): void { this.updateMenus(); this.notificationCenter.onPlatformInstalled(this.updateMenus.bind(this)); this.notificationCenter.onPlatformUninstalled(this.updateMenus.bind(this)); diff --git a/arduino-ide-extension/src/browser/contributions/burn-bootloader.ts b/arduino-ide-extension/src/browser/contributions/burn-bootloader.ts index e7267ae34..1acda7d15 100644 --- a/arduino-ide-extension/src/browser/contributions/burn-bootloader.ts +++ b/arduino-ide-extension/src/browser/contributions/burn-bootloader.ts @@ -28,15 +28,15 @@ export class BurnBootloader extends SketchContribution { protected readonly boardsServiceClientImpl: BoardsServiceProvider; @inject(OutputChannelManager) - protected readonly outputChannelManager: OutputChannelManager; + protected override readonly outputChannelManager: OutputChannelManager; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(BurnBootloader.Commands.BURN_BOOTLOADER, { execute: () => this.burnBootloader(), }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.TOOLS__BOARD_SETTINGS_GROUP, { commandId: BurnBootloader.Commands.BURN_BOOTLOADER.id, label: nls.localize( diff --git a/arduino-ide-extension/src/browser/contributions/close.ts b/arduino-ide-extension/src/browser/contributions/close.ts index f27b832cf..3658be152 100644 --- a/arduino-ide-extension/src/browser/contributions/close.ts +++ b/arduino-ide-extension/src/browser/contributions/close.ts @@ -23,15 +23,15 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class Close extends SketchContribution { @inject(EditorManager) - protected readonly editorManager: EditorManager; + protected override readonly editorManager: EditorManager; protected shell: ApplicationShell; - onStart(app: FrontendApplication): void { + override onStart(app: FrontendApplication): void { this.shell = app.shell; } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(Close.Commands.CLOSE, { execute: async () => { // Close current editor if closeable. @@ -106,7 +106,7 @@ export class Close extends SketchContribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { commandId: Close.Commands.CLOSE.id, label: nls.localize('vscode/editor.contribution/close', 'Close'), @@ -114,7 +114,7 @@ export class Close extends SketchContribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: Close.Commands.CLOSE.id, keybinding: 'CtrlCmd+W', diff --git a/arduino-ide-extension/src/browser/contributions/debug.ts b/arduino-ide-extension/src/browser/contributions/debug.ts index 0a2614ad4..05121988a 100644 --- a/arduino-ide-extension/src/browser/contributions/debug.ts +++ b/arduino-ide-extension/src/browser/contributions/debug.ts @@ -66,7 +66,7 @@ export class Debug extends SketchContribution { onDidChange: this.onDisabledMessageDidChange as Event, }; - onStart(): void { + override onStart(): void { this.onDisabledMessageDidChange( () => (this.debugToolbarItem.tooltip = `${ @@ -127,7 +127,7 @@ export class Debug extends SketchContribution { refreshState(); } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(Debug.Commands.START_DEBUGGING, { execute: () => this.startDebug(), isVisible: (widget) => @@ -136,7 +136,7 @@ export class Debug extends SketchContribution { }); } - registerToolbarItems(registry: TabBarToolbarRegistry): void { + override registerToolbarItems(registry: TabBarToolbarRegistry): void { registry.registerItem(this.debugToolbarItem); } diff --git a/arduino-ide-extension/src/browser/contributions/edit-contributions.ts b/arduino-ide-extension/src/browser/contributions/edit-contributions.ts index 3fee31490..6b77d5163 100644 --- a/arduino-ide-extension/src/browser/contributions/edit-contributions.ts +++ b/arduino-ide-extension/src/browser/contributions/edit-contributions.ts @@ -28,7 +28,7 @@ export class EditContributions extends Contribution { @inject(PreferenceService) protected readonly preferences: PreferenceService; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(EditContributions.Commands.GO_TO_LINE, { execute: () => this.run('editor.action.gotoLine'), }); @@ -93,7 +93,7 @@ ${value} }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.EDIT__TEXT_CONTROL_GROUP, { commandId: CommonCommands.CUT.id, order: '0', @@ -201,7 +201,7 @@ ${value} }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: EditContributions.Commands.COPY_FOR_FORUM.id, keybinding: 'CtrlCmd+Shift+C', diff --git a/arduino-ide-extension/src/browser/contributions/examples.ts b/arduino-ide-extension/src/browser/contributions/examples.ts index 7a0e04daa..8b4a61a70 100644 --- a/arduino-ide-extension/src/browser/contributions/examples.ts +++ b/arduino-ide-extension/src/browser/contributions/examples.ts @@ -54,7 +54,7 @@ export abstract class Examples extends SketchContribution { // NOOP } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { try { // This is a hack the ensures the desired menu ordering! We cannot use https://github.com/eclipse-theia/theia/pull/8377 due to ATL-222. const index = ArduinoMenus.FILE__EXAMPLES_SUBMENU.length - 1; @@ -161,7 +161,7 @@ export abstract class Examples extends SketchContribution { @injectable() export class BuiltInExamples extends Examples { - onStart(): void { + override onStart(): void { this.register(); // no `await` } @@ -201,13 +201,13 @@ export class LibraryExamples extends Examples { protected readonly queue = new PQueue({ autoStart: true, concurrency: 1 }); - onStart(): void { + override onStart(): void { this.register(); // no `await` this.notificationCenter.onLibraryInstalled(() => this.register()); this.notificationCenter.onLibraryUninstalled(() => this.register()); } - protected handleBoardChanged(board: Board | undefined): void { + protected override handleBoardChanged(board: Board | undefined): void { this.register(board); } diff --git a/arduino-ide-extension/src/browser/contributions/help.ts b/arduino-ide-extension/src/browser/contributions/help.ts index 63c3da323..36e09f52e 100644 --- a/arduino-ide-extension/src/browser/contributions/help.ts +++ b/arduino-ide-extension/src/browser/contributions/help.ts @@ -28,7 +28,7 @@ export class Help extends Contribution { @inject(QuickInputService) protected readonly quickInputService: QuickInputService; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { const open = (url: string) => this.windowService.openNewWindow(url, { external: true }); const createOpenHandler = (url: string) => @@ -92,7 +92,7 @@ export class Help extends Contribution { ); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.unregisterMenuAction({ commandId: ElectronCommands.TOGGLE_DEVELOPER_TOOLS.id, }); @@ -136,7 +136,7 @@ export class Help extends Contribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: Help.Commands.FIND_IN_REFERENCE.id, keybinding: 'CtrlCmd+Shift+F', diff --git a/arduino-ide-extension/src/browser/contributions/include-library.ts b/arduino-ide-extension/src/browser/contributions/include-library.ts index f8f07e7a9..3f1c35baf 100644 --- a/arduino-ide-extension/src/browser/contributions/include-library.ts +++ b/arduino-ide-extension/src/browser/contributions/include-library.ts @@ -30,7 +30,7 @@ export class IncludeLibrary extends SketchContribution { protected readonly mainMenuManager: MainMenuManager; @inject(EditorManager) - protected readonly editorManager: EditorManager; + protected override readonly editorManager: EditorManager; @inject(NotificationCenter) protected readonly notificationCenter: NotificationCenter; @@ -44,7 +44,7 @@ export class IncludeLibrary extends SketchContribution { protected readonly queue = new PQueue({ autoStart: true, concurrency: 1 }); protected readonly toDispose = new DisposableCollection(); - onStart(): void { + override onStart(): void { this.updateMenuActions(); this.boardsServiceClient.onBoardsConfigChanged(() => this.updateMenuActions() @@ -55,7 +55,7 @@ export class IncludeLibrary extends SketchContribution { ); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { // `Include Library` submenu const includeLibMenuPath = [ ...ArduinoMenus.SKETCH__UTILS_GROUP, @@ -78,7 +78,7 @@ export class IncludeLibrary extends SketchContribution { }); } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY, { execute: async (arg) => { if (LibraryPackage.is(arg)) { diff --git a/arduino-ide-extension/src/browser/contributions/new-sketch.ts b/arduino-ide-extension/src/browser/contributions/new-sketch.ts index bc6cdcf14..685ae7e2b 100644 --- a/arduino-ide-extension/src/browser/contributions/new-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/new-sketch.ts @@ -14,7 +14,7 @@ import { @injectable() export class NewSketch extends SketchContribution { - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(NewSketch.Commands.NEW_SKETCH, { execute: () => this.newSketch(), }); @@ -25,7 +25,7 @@ export class NewSketch extends SketchContribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { commandId: NewSketch.Commands.NEW_SKETCH.id, label: nls.localize('arduino/sketch/new', 'New'), @@ -33,14 +33,14 @@ export class NewSketch extends SketchContribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: NewSketch.Commands.NEW_SKETCH.id, keybinding: 'CtrlCmd+N', }); } - registerToolbarItems(registry: TabBarToolbarRegistry): void { + override registerToolbarItems(registry: TabBarToolbarRegistry): void { registry.registerItem({ id: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id, command: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id, diff --git a/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts b/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts index d5f4ddbcc..f3ee7b644 100644 --- a/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts @@ -35,7 +35,7 @@ export class OpenRecentSketch extends SketchContribution { protected toDisposeBeforeRegister = new Map(); - onStart(): void { + override onStart(): void { const refreshMenu = (sketches: Sketch[]) => { this.register(sketches); this.mainMenuManager.update(); @@ -46,7 +46,7 @@ export class OpenRecentSketch extends SketchContribution { this.sketchService.recentlyOpenedSketches().then(refreshMenu); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerSubmenu( ArduinoMenus.FILE__OPEN_RECENT_SUBMENU, nls.localize('arduino/sketch/openRecent', 'Open Recent'), diff --git a/arduino-ide-extension/src/browser/contributions/open-sketch-external.ts b/arduino-ide-extension/src/browser/contributions/open-sketch-external.ts index 4a753082a..03207126f 100644 --- a/arduino-ide-extension/src/browser/contributions/open-sketch-external.ts +++ b/arduino-ide-extension/src/browser/contributions/open-sketch-external.ts @@ -13,13 +13,13 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class OpenSketchExternal extends SketchContribution { - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(OpenSketchExternal.Commands.OPEN_EXTERNAL, { execute: () => this.openExternal(), }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.SKETCH__UTILS_GROUP, { commandId: OpenSketchExternal.Commands.OPEN_EXTERNAL.id, label: nls.localize('arduino/sketch/showFolder', 'Show Sketch Folder'), @@ -27,7 +27,7 @@ export class OpenSketchExternal extends SketchContribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: OpenSketchExternal.Commands.OPEN_EXTERNAL.id, keybinding: 'CtrlCmd+Alt+K', diff --git a/arduino-ide-extension/src/browser/contributions/open-sketch.ts b/arduino-ide-extension/src/browser/contributions/open-sketch.ts index fefbbbb6c..f110addc3 100644 --- a/arduino-ide-extension/src/browser/contributions/open-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/open-sketch.ts @@ -43,7 +43,7 @@ export class OpenSketch extends SketchContribution { protected readonly toDispose = new DisposableCollection(); - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(OpenSketch.Commands.OPEN_SKETCH, { execute: (arg) => Sketch.is(arg) ? this.openSketch(arg) : this.openSketch(), @@ -116,7 +116,7 @@ export class OpenSketch extends SketchContribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { commandId: OpenSketch.Commands.OPEN_SKETCH.id, label: nls.localize('vscode/workspaceActions/openFileFolder', 'Open...'), @@ -124,14 +124,14 @@ export class OpenSketch extends SketchContribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: OpenSketch.Commands.OPEN_SKETCH.id, keybinding: 'CtrlCmd+O', }); } - registerToolbarItems(registry: TabBarToolbarRegistry): void { + override registerToolbarItems(registry: TabBarToolbarRegistry): void { registry.registerItem({ id: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id, command: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id, diff --git a/arduino-ide-extension/src/browser/contributions/quit-app.ts b/arduino-ide-extension/src/browser/contributions/quit-app.ts index d12e5fdfa..17a7874dd 100644 --- a/arduino-ide-extension/src/browser/contributions/quit-app.ts +++ b/arduino-ide-extension/src/browser/contributions/quit-app.ts @@ -13,7 +13,7 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class QuitApp extends Contribution { - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { if (!isOSX) { registry.registerCommand(QuitApp.Commands.QUIT_APP, { execute: () => remote.app.quit(), @@ -21,7 +21,7 @@ export class QuitApp extends Contribution { } } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { // On macOS we will get the `Quit ${YOUR_APP_NAME}` menu item natively, no need to duplicate it. if (!isOSX) { registry.registerMenuAction(ArduinoMenus.FILE__QUIT_GROUP, { @@ -32,7 +32,7 @@ export class QuitApp extends Contribution { } } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { if (!isOSX) { registry.registerKeybinding({ command: QuitApp.Commands.QUIT_APP.id, diff --git a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts index cafb51b29..2cd709a42 100644 --- a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts @@ -22,18 +22,18 @@ export class SaveAsSketch extends SketchContribution { protected readonly applicationShell: ApplicationShell; @inject(EditorManager) - protected readonly editorManager: EditorManager; + protected override readonly editorManager: EditorManager; @inject(WindowService) protected readonly windowService: WindowService; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(SaveAsSketch.Commands.SAVE_AS_SKETCH, { execute: (args) => this.saveAs(args), }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { commandId: SaveAsSketch.Commands.SAVE_AS_SKETCH.id, label: nls.localize('vscode/fileCommands/saveAs', 'Save As...'), @@ -41,7 +41,7 @@ export class SaveAsSketch extends SketchContribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: SaveAsSketch.Commands.SAVE_AS_SKETCH.id, keybinding: 'CtrlCmd+Shift+S', diff --git a/arduino-ide-extension/src/browser/contributions/save-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-sketch.ts index 2792fd8eb..0df21d32c 100644 --- a/arduino-ide-extension/src/browser/contributions/save-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/save-sketch.ts @@ -15,7 +15,7 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class SaveSketch extends SketchContribution { - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(SaveSketch.Commands.SAVE_SKETCH, { execute: () => this.saveSketch(), }); @@ -27,7 +27,7 @@ export class SaveSketch extends SketchContribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.FILE__SKETCH_GROUP, { commandId: SaveSketch.Commands.SAVE_SKETCH.id, label: nls.localize('vscode/fileCommands/save', 'Save'), @@ -35,14 +35,14 @@ export class SaveSketch extends SketchContribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: SaveSketch.Commands.SAVE_SKETCH.id, keybinding: 'CtrlCmd+S', }); } - registerToolbarItems(registry: TabBarToolbarRegistry): void { + override registerToolbarItems(registry: TabBarToolbarRegistry): void { registry.registerItem({ id: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id, command: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id, diff --git a/arduino-ide-extension/src/browser/contributions/settings.ts b/arduino-ide-extension/src/browser/contributions/settings.ts index a6321c511..32030809e 100644 --- a/arduino-ide-extension/src/browser/contributions/settings.ts +++ b/arduino-ide-extension/src/browser/contributions/settings.ts @@ -18,7 +18,7 @@ export class Settings extends SketchContribution { protected settingsOpened = false; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(Settings.Commands.OPEN, { execute: async () => { let settings: Preferences | undefined = undefined; @@ -39,7 +39,7 @@ export class Settings extends SketchContribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.FILE__PREFERENCES_GROUP, { commandId: Settings.Commands.OPEN.id, label: @@ -52,7 +52,7 @@ export class Settings extends SketchContribution { registry.registerSubmenu(ArduinoMenus.FILE__ADVANCED_SUBMENU, 'Advanced'); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: Settings.Commands.OPEN.id, keybinding: 'CtrlCmd+,', diff --git a/arduino-ide-extension/src/browser/contributions/sketch-control.ts b/arduino-ide-extension/src/browser/contributions/sketch-control.ts index fa4974ce3..d8a967847 100644 --- a/arduino-ide-extension/src/browser/contributions/sketch-control.ts +++ b/arduino-ide-extension/src/browser/contributions/sketch-control.ts @@ -35,7 +35,7 @@ export class SketchControl extends SketchContribution { protected readonly contextMenuRenderer: ContextMenuRenderer; @inject(EditorManager) - protected readonly editorManager: EditorManager; + protected override readonly editorManager: EditorManager; @inject(SketchesServiceClientImpl) protected readonly sketchesServiceClient: SketchesServiceClientImpl; @@ -46,7 +46,7 @@ export class SketchControl extends SketchContribution { protected readonly toDisposeBeforeCreateNewContextMenu = new DisposableCollection(); - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand( SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR, { @@ -200,7 +200,7 @@ export class SketchControl extends SketchContribution { ); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction( ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, { @@ -228,7 +228,7 @@ export class SketchControl extends SketchContribution { ); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: WorkspaceCommands.NEW_FILE.id, keybinding: 'CtrlCmd+Shift+N', @@ -243,7 +243,7 @@ export class SketchControl extends SketchContribution { }); } - registerToolbarItems(registry: TabBarToolbarRegistry): void { + override registerToolbarItems(registry: TabBarToolbarRegistry): void { registry.registerItem({ id: SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id, command: SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id, diff --git a/arduino-ide-extension/src/browser/contributions/sketchbook.ts b/arduino-ide-extension/src/browser/contributions/sketchbook.ts index 2b57cb171..676eba169 100644 --- a/arduino-ide-extension/src/browser/contributions/sketchbook.ts +++ b/arduino-ide-extension/src/browser/contributions/sketchbook.ts @@ -12,10 +12,10 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class Sketchbook extends Examples { @inject(CommandRegistry) - protected readonly commandRegistry: CommandRegistry; + protected override readonly commandRegistry: CommandRegistry; @inject(MenuModelRegistry) - protected readonly menuRegistry: MenuModelRegistry; + protected override readonly menuRegistry: MenuModelRegistry; @inject(MainMenuManager) protected readonly mainMenuManager: MainMenuManager; @@ -23,7 +23,7 @@ export class Sketchbook extends Examples { @inject(NotificationCenter) protected readonly notificationCenter: NotificationCenter; - onStart(): void { + override onStart(): void { this.sketchService.getSketches({}).then((container) => { this.register(container); this.mainMenuManager.update(); @@ -36,7 +36,7 @@ export class Sketchbook extends Examples { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerSubmenu( ArduinoMenus.FILE__SKETCHBOOK_SUBMENU, nls.localize('arduino/sketch/sketchbook', 'Sketchbook'), @@ -53,7 +53,7 @@ export class Sketchbook extends Examples { ); } - protected createHandler(uri: string): CommandHandler { + protected override createHandler(uri: string): CommandHandler { return { execute: async () => { const sketch = await this.sketchService.loadSketch(uri); diff --git a/arduino-ide-extension/src/browser/contributions/upload-certificate.ts b/arduino-ide-extension/src/browser/contributions/upload-certificate.ts index b57f8d036..91292eb49 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-certificate.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-certificate.ts @@ -39,7 +39,7 @@ export class UploadCertificate extends Contribution { protected dialogOpened = false; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(UploadCertificate.Commands.OPEN, { execute: async () => { try { @@ -93,7 +93,7 @@ export class UploadCertificate extends Contribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.TOOLS__FIRMWARE_UPLOADER_GROUP, { commandId: UploadCertificate.Commands.OPEN.id, label: UploadCertificate.Commands.OPEN.label, diff --git a/arduino-ide-extension/src/browser/contributions/upload-firmware.ts b/arduino-ide-extension/src/browser/contributions/upload-firmware.ts index 8b3f4f94f..6fc566904 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-firmware.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-firmware.ts @@ -16,7 +16,7 @@ export class UploadFirmware extends Contribution { protected dialogOpened = false; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(UploadFirmware.Commands.OPEN, { execute: async () => { try { @@ -30,7 +30,7 @@ export class UploadFirmware extends Contribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.TOOLS__FIRMWARE_UPLOADER_GROUP, { commandId: UploadFirmware.Commands.OPEN.id, label: UploadFirmware.Commands.OPEN.label, diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index 1a198d4b1..eb58c264b 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -72,7 +72,7 @@ export class UploadSketch extends SketchContribution { return fqbn + '|' + address; } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH, { execute: async () => { const key = this.selectedFqbnAddress(); @@ -134,7 +134,7 @@ export class UploadSketch extends SketchContribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { this.menuActionsDisposables.dispose(); this.menuActionsDisposables.push( @@ -177,7 +177,7 @@ export class UploadSketch extends SketchContribution { ); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: UploadSketch.Commands.UPLOAD_SKETCH.id, keybinding: 'CtrlCmd+U', @@ -188,7 +188,7 @@ export class UploadSketch extends SketchContribution { }); } - registerToolbarItems(registry: TabBarToolbarRegistry): void { + override registerToolbarItems(registry: TabBarToolbarRegistry): void { registry.registerItem({ id: UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR.id, command: UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR.id, diff --git a/arduino-ide-extension/src/browser/contributions/verify-sketch.ts b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts index 4ebc5cff0..e6946cba4 100644 --- a/arduino-ide-extension/src/browser/contributions/verify-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts @@ -31,7 +31,7 @@ export class VerifySketch extends SketchContribution { protected verifyInProgress = false; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, { execute: () => this.verifySketch(), isEnabled: () => !this.verifyInProgress, @@ -50,7 +50,7 @@ export class VerifySketch extends SketchContribution { }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, { commandId: VerifySketch.Commands.VERIFY_SKETCH.id, label: nls.localize('arduino/sketch/verifyOrCompile', 'Verify/Compile'), @@ -66,7 +66,7 @@ export class VerifySketch extends SketchContribution { }); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.registerKeybinding({ command: VerifySketch.Commands.VERIFY_SKETCH.id, keybinding: 'CtrlCmd+R', @@ -77,7 +77,7 @@ export class VerifySketch extends SketchContribution { }); } - registerToolbarItems(registry: TabBarToolbarRegistry): void { + override registerToolbarItems(registry: TabBarToolbarRegistry): void { registry.registerItem({ id: VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR.id, command: VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR.id, diff --git a/arduino-ide-extension/src/browser/create/create-api.ts b/arduino-ide-extension/src/browser/create/create-api.ts index 19fa98ddc..1e8740a96 100644 --- a/arduino-ide-extension/src/browser/create/create-api.ts +++ b/arduino-ide-extension/src/browser/create/create-api.ts @@ -117,11 +117,11 @@ export class CreateApi { headers, }) ).sketches; - if (partialSketches.length != 0) { + if (partialSketches.length !== 0) { result.sketches = result.sketches.concat(partialSketches); } currentOffset = currentOffset + limit; - } while (partialSketches.length != 0); + } while (partialSketches.length !== 0); result.sketches.forEach((sketch) => this.sketchCache.addSketch(sketch)); return result.sketches; diff --git a/arduino-ide-extension/src/browser/dialogs/certificate-uploader/certificate-uploader-dialog.tsx b/arduino-ide-extension/src/browser/dialogs/certificate-uploader/certificate-uploader-dialog.tsx index 77bc89240..4a9d2f4da 100644 --- a/arduino-ide-extension/src/browser/dialogs/certificate-uploader/certificate-uploader-dialog.tsx +++ b/arduino-ide-extension/src/browser/dialogs/certificate-uploader/certificate-uploader-dialog.tsx @@ -139,7 +139,7 @@ export class UploadCertificateDialog extends AbstractDialog { constructor( @inject(UploadCertificateDialogProps) - protected readonly props: UploadCertificateDialogProps + protected override readonly props: UploadCertificateDialogProps ) { super({ title: nls.localize( @@ -155,7 +155,7 @@ export class UploadCertificateDialog extends AbstractDialog { return; } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { if (this.widget.isAttached) { Widget.detach(this.widget); } @@ -165,21 +165,21 @@ export class UploadCertificateDialog extends AbstractDialog { this.update(); } - protected onUpdateRequest(msg: Message): void { + protected override onUpdateRequest(msg: Message): void { super.onUpdateRequest(msg); this.widget.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); this.widget.activate(); } - protected handleEnter(event: KeyboardEvent): boolean | void { + protected override handleEnter(event: KeyboardEvent): boolean | void { return false; } - close(): void { + override close(): void { if (this.busy) { return; } diff --git a/arduino-ide-extension/src/browser/dialogs/cloud-share-sketch-dialog.tsx b/arduino-ide-extension/src/browser/dialogs/cloud-share-sketch-dialog.tsx index 9e5b678af..dbbad77e6 100644 --- a/arduino-ide-extension/src/browser/dialogs/cloud-share-sketch-dialog.tsx +++ b/arduino-ide-extension/src/browser/dialogs/cloud-share-sketch-dialog.tsx @@ -149,7 +149,7 @@ export class ShareSketchDialog extends AbstractDialog { constructor( @inject(ShareSketchDialogProps) - protected readonly props: ShareSketchDialogProps + protected override readonly props: ShareSketchDialogProps ) { super({ title: props.title }); this.contentNode.classList.add('arduino-share-sketch-dialog'); @@ -159,7 +159,7 @@ export class ShareSketchDialog extends AbstractDialog { get value(): void { return; } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { if (this.widget.isAttached) { Widget.detach(this.widget); } @@ -168,12 +168,12 @@ export class ShareSketchDialog extends AbstractDialog { this.update(); } - protected onUpdateRequest(msg: Message): void { + protected override onUpdateRequest(msg: Message): void { super.onUpdateRequest(msg); this.widget.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); this.widget.activate(); } diff --git a/arduino-ide-extension/src/browser/dialogs/do-not-ask-again-dialog.ts b/arduino-ide-extension/src/browser/dialogs/do-not-ask-again-dialog.ts index 474573ff8..a7982aca5 100644 --- a/arduino-ide-extension/src/browser/dialogs/do-not-ask-again-dialog.ts +++ b/arduino-ide-extension/src/browser/dialogs/do-not-ask-again-dialog.ts @@ -19,7 +19,7 @@ export class DoNotAskAgainConfirmDialog extends ConfirmDialog { constructor( @inject(DoNotAskAgainDialogProps) - protected readonly props: DoNotAskAgainDialogProps + protected override readonly props: DoNotAskAgainDialogProps ) { super(props); this.controlPanel.removeChild(this.errorMessageNode); @@ -42,7 +42,7 @@ export class DoNotAskAgainConfirmDialog extends ConfirmDialog { this.doNotAskAgainCheckbox.type = 'checkbox'; } - protected async accept(): Promise { + protected override async accept(): Promise { if (!this.resolve) { return; } @@ -65,7 +65,7 @@ export class DoNotAskAgainConfirmDialog extends ConfirmDialog { } } - protected setErrorMessage(error: DialogError): void { + protected override setErrorMessage(error: DialogError): void { if (this.acceptButton) { this.acceptButton.disabled = !DialogError.getResult(error); } diff --git a/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx b/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx index 9dd8a9b6b..27a3484dd 100644 --- a/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx +++ b/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx @@ -56,7 +56,7 @@ export class UploadFirmwareDialogWidget extends ReactWidget { .finally(() => this.busyCallback(false)); } - onCloseRequest(msg: Message): void { + protected override onCloseRequest(msg: Message): void { super.onCloseRequest(msg); this.isOpen = new Object(); } @@ -88,7 +88,7 @@ export class UploadFirmwareDialog extends AbstractDialog { constructor( @inject(UploadFirmwareDialogProps) - protected readonly props: UploadFirmwareDialogProps + protected override readonly props: UploadFirmwareDialogProps ) { super({ title: UploadFirmware.Commands.OPEN.label || '' }); this.contentNode.classList.add('firmware-uploader-dialog'); @@ -99,7 +99,7 @@ export class UploadFirmwareDialog extends AbstractDialog { return; } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { if (this.widget.isAttached) { Widget.detach(this.widget); } @@ -109,21 +109,21 @@ export class UploadFirmwareDialog extends AbstractDialog { this.update(); } - protected onUpdateRequest(msg: Message): void { + protected override onUpdateRequest(msg: Message): void { super.onUpdateRequest(msg); this.widget.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); this.widget.activate(); } - protected handleEnter(event: KeyboardEvent): boolean | void { + protected override handleEnter(event: KeyboardEvent): boolean | void { return false; } - close(): void { + override close(): void { if (this.busy) { return; } diff --git a/arduino-ide-extension/src/browser/dialogs/ide-updater/ide-updater-dialog.tsx b/arduino-ide-extension/src/browser/dialogs/ide-updater/ide-updater-dialog.tsx index 215e00f31..2b0b952bd 100644 --- a/arduino-ide-extension/src/browser/dialogs/ide-updater/ide-updater-dialog.tsx +++ b/arduino-ide-extension/src/browser/dialogs/ide-updater/ide-updater-dialog.tsx @@ -70,7 +70,7 @@ export class IDEUpdaterDialogWidget extends ReactWidget { this.close(); } - close(): void { + override close(): void { super.close(); this.onClose(); } @@ -122,7 +122,7 @@ export class IDEUpdaterDialog extends AbstractDialog { constructor( @inject(IDEUpdaterDialogProps) - protected readonly props: IDEUpdaterDialogProps + protected override readonly props: IDEUpdaterDialogProps ) { super({ title: nls.localize( @@ -138,7 +138,7 @@ export class IDEUpdaterDialog extends AbstractDialog { return this.widget.updateInfo; } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { if (this.widget.isAttached) { Widget.detach(this.widget); } @@ -147,7 +147,7 @@ export class IDEUpdaterDialog extends AbstractDialog { this.update(); } - async open( + override async open( data: UpdateInfo | undefined = undefined ): Promise { if (data && data.version) { @@ -156,17 +156,17 @@ export class IDEUpdaterDialog extends AbstractDialog { } } - protected onUpdateRequest(msg: Message): void { + protected override onUpdateRequest(msg: Message): void { super.onUpdateRequest(msg); this.widget.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); this.widget.activate(); } - close(): void { + override close(): void { this.widget.dispose(); super.close(); } diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx index 33272a32f..86d0d6847 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-component.tsx @@ -32,7 +32,7 @@ export class SettingsComponent extends React.Component< super(props); } - componentDidUpdate( + override componentDidUpdate( _: SettingsComponent.Props, prevState: SettingsComponent.State ): void { @@ -49,7 +49,7 @@ export class SettingsComponent extends React.Component< } } - componentDidMount(): void { + override componentDidMount(): void { this.props.settingsService .settings() .then((settings) => @@ -67,11 +67,11 @@ export class SettingsComponent extends React.Component< ]); } - componentWillUnmount(): void { + override componentWillUnmount(): void { this.toDispose.dispose(); } - render(): React.ReactNode { + override render(): React.ReactNode { if (!this.state) { return
; } diff --git a/arduino-ide-extension/src/browser/dialogs/settings/settings-dialog.tsx b/arduino-ide-extension/src/browser/dialogs/settings/settings-dialog.tsx index 498de0cfa..9c51479c9 100644 --- a/arduino-ide-extension/src/browser/dialogs/settings/settings-dialog.tsx +++ b/arduino-ide-extension/src/browser/dialogs/settings/settings-dialog.tsx @@ -56,7 +56,7 @@ export class SettingsDialog extends AbstractDialog> { constructor( @inject(SettingsDialogProps) - protected readonly props: SettingsDialogProps + protected override readonly props: SettingsDialogProps ) { super(props); this.contentNode.classList.add('arduino-settings-dialog'); @@ -73,7 +73,7 @@ export class SettingsDialog extends AbstractDialog> { ); } - protected async isValid(settings: Promise): Promise { + protected override async isValid(settings: Promise): Promise { const result = await this.settingsService.validate(settings); if (typeof result === 'string') { return result; @@ -85,7 +85,7 @@ export class SettingsDialog extends AbstractDialog> { return this.settingsService.settings(); } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { if (this.widget.isAttached) { Widget.detach(this.widget); } @@ -97,12 +97,12 @@ export class SettingsDialog extends AbstractDialog> { this.update(); } - protected onUpdateRequest(msg: Message): void { + protected override onUpdateRequest(msg: Message): void { super.onUpdateRequest(msg); this.widget.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); // calling settingsService.reset() in order to reload the settings from the preferenceService @@ -172,17 +172,17 @@ export class AdditionalUrlsDialog extends AbstractDialog { return AdditionalUrls.parse(this.textArea.value, 'newline'); } - protected onAfterAttach(message: Message): void { + protected override onAfterAttach(message: Message): void { super.onAfterAttach(message); this.addUpdateListener(this.textArea, 'input'); } - protected onActivateRequest(message: Message): void { + protected override onActivateRequest(message: Message): void { super.onActivateRequest(message); this.textArea.focus(); } - protected handleEnter(event: KeyboardEvent): boolean | void { + protected override handleEnter(event: KeyboardEvent): boolean | void { if (event.target instanceof HTMLInputElement) { return super.handleEnter(event); } diff --git a/arduino-ide-extension/src/browser/dialogs/user-fields/user-fields-dialog.tsx b/arduino-ide-extension/src/browser/dialogs/user-fields/user-fields-dialog.tsx index 19a7aee37..8835fd355 100644 --- a/arduino-ide-extension/src/browser/dialogs/user-fields/user-fields-dialog.tsx +++ b/arduino-ide-extension/src/browser/dialogs/user-fields/user-fields-dialog.tsx @@ -61,7 +61,7 @@ export class UserFieldsDialog extends AbstractDialog { constructor( @inject(UserFieldsDialogProps) - protected readonly props: UserFieldsDialogProps + protected override readonly props: UserFieldsDialogProps ) { super({ title: UploadSketch.Commands.UPLOAD_WITH_CONFIGURATION.label || '', @@ -83,7 +83,7 @@ export class UserFieldsDialog extends AbstractDialog { return this.widget.currentUserFields; } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { if (this.widget.isAttached) { Widget.detach(this.widget); } @@ -92,17 +92,17 @@ export class UserFieldsDialog extends AbstractDialog { this.update(); } - protected onUpdateRequest(msg: Message): void { + protected override onUpdateRequest(msg: Message): void { super.onUpdateRequest(msg); this.widget.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); this.widget.activate(); } - protected async accept(): Promise { + protected override async accept(): Promise { // If the user presses enter and at least // a field is empty don't accept the input for (const field of this.value) { @@ -113,7 +113,7 @@ export class UserFieldsDialog extends AbstractDialog { return super.accept(); } - close(): void { + override close(): void { this.widget.resetUserFieldsValue(); this.widget.close(); super.close(); diff --git a/arduino-ide-extension/src/browser/library/library-list-widget.ts b/arduino-ide-extension/src/browser/library/library-list-widget.ts index 033e1802c..dc82199e8 100644 --- a/arduino-ide-extension/src/browser/library/library-list-widget.ts +++ b/arduino-ide-extension/src/browser/library/library-list-widget.ts @@ -38,7 +38,7 @@ export class LibraryListWidget extends ListWidget { } @postConstruct() - protected init(): void { + protected override init(): void { super.init(); this.toDispose.pushAll([ this.notificationCenter.onLibraryInstalled(() => this.refresh(undefined)), @@ -48,7 +48,7 @@ export class LibraryListWidget extends ListWidget { ]); } - protected async install({ + protected override async install({ item, progressId, version, @@ -158,7 +158,7 @@ export class LibraryListWidget extends ListWidget { } } - protected async uninstall({ + protected override async uninstall({ item, progressId, }: { @@ -199,7 +199,7 @@ class MessageBoxDialog extends AbstractDialog { }); } - protected onCloseRequest(message: Message): void { + protected override onCloseRequest(message: Message): void { super.onCloseRequest(message); this.accept(); } @@ -217,7 +217,7 @@ class MessageBoxDialog extends AbstractDialog { return message; } - protected handleEnter(event: KeyboardEvent): boolean | void { + protected override handleEnter(event: KeyboardEvent): boolean | void { this.response = 0; super.handleEnter(event); } diff --git a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts index 1a06e8472..37a3b0679 100644 --- a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts @@ -28,7 +28,7 @@ export class LibraryListWidgetFrontendContribution this.openView(); } - registerMenus(menus: MenuModelRegistry): void { + override registerMenus(menus: MenuModelRegistry): void { if (this.toggleCommand) { menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, { commandId: this.toggleCommand.id, diff --git a/arduino-ide-extension/src/browser/serial/monitor/monitor-view-contribution.tsx b/arduino-ide-extension/src/browser/serial/monitor/monitor-view-contribution.tsx index 43b5a0a12..c29f7ca3e 100644 --- a/arduino-ide-extension/src/browser/serial/monitor/monitor-view-contribution.tsx +++ b/arduino-ide-extension/src/browser/serial/monitor/monitor-view-contribution.tsx @@ -62,7 +62,7 @@ export class MonitorViewContribution }); } - registerMenus(menus: MenuModelRegistry): void { + override registerMenus(menus: MenuModelRegistry): void { if (this.toggleCommand) { menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, { commandId: this.toggleCommand.id, @@ -95,7 +95,7 @@ export class MonitorViewContribution }); } - registerCommands(commands: CommandRegistry): void { + override registerCommands(commands: CommandRegistry): void { commands.registerCommand(SerialMonitor.Commands.CLEAR_OUTPUT, { isEnabled: (widget) => widget instanceof MonitorWidget, isVisible: (widget) => widget instanceof MonitorWidget, diff --git a/arduino-ide-extension/src/browser/serial/monitor/monitor-widget.tsx b/arduino-ide-extension/src/browser/serial/monitor/monitor-widget.tsx index cbe94e58b..24d6449e7 100644 --- a/arduino-ide-extension/src/browser/serial/monitor/monitor-widget.tsx +++ b/arduino-ide-extension/src/browser/serial/monitor/monitor-widget.tsx @@ -75,21 +75,21 @@ export class MonitorWidget extends ReactWidget { this.update(); } - dispose(): void { + override dispose(): void { super.dispose(); } - protected onAfterAttach(msg: Message): void { + protected override onAfterAttach(msg: Message): void { super.onAfterAttach(msg); this.serialConnection.openWSToBE(); } - onCloseRequest(msg: Message): void { + protected override onCloseRequest(msg: Message): void { this.closing = true; super.onCloseRequest(msg); } - protected onUpdateRequest(msg: Message): void { + protected override onUpdateRequest(msg: Message): void { // TODO: `this.isAttached` // See: https://github.com/eclipse-theia/theia/issues/6704#issuecomment-562574713 if (!this.closing && this.isAttached) { @@ -97,13 +97,13 @@ export class MonitorWidget extends ReactWidget { } } - protected onResize(msg: Widget.ResizeMessage): void { + protected override onResize(msg: Widget.ResizeMessage): void { super.onResize(msg); this.widgetHeight = msg.height; this.update(); } - protected onActivateRequest(msg: Message): void { + protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); (this.focusNode || this.node).focus(); } diff --git a/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx b/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx index 15215307d..8000d9fe4 100644 --- a/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx +++ b/arduino-ide-extension/src/browser/serial/monitor/serial-monitor-send-input.tsx @@ -32,7 +32,7 @@ export class SerialMonitorSendInput extends React.Component< this.onKeyDown = this.onKeyDown.bind(this); } - componentDidMount(): void { + override componentDidMount(): void { this.props.serialConnection.isBESerialConnected().then((connected) => { this.setState({ connected }); }); @@ -50,12 +50,12 @@ export class SerialMonitorSendInput extends React.Component< ]); } - componentWillUnmount(): void { + override componentWillUnmount(): void { // TODO: "Your preferred browser's local storage is almost full." Discard `content` before saving layout? this.toDisposeBeforeUnmount.dispose(); } - render(): React.ReactNode { + override render(): React.ReactNode { return ( { @@ -87,7 +87,7 @@ export class SerialMonitorOutput extends React.Component< ]); } - componentWillUnmount(): void { + override componentWillUnmount(): void { // TODO: "Your preferred browser's local storage is almost full." Discard `content` before saving layout? this.toDisposeBeforeUnmount.dispose(); } diff --git a/arduino-ide-extension/src/browser/serial/plotter/plotter-frontend-contribution.ts b/arduino-ide-extension/src/browser/serial/plotter/plotter-frontend-contribution.ts index da2d7384a..c2f23ae8f 100644 --- a/arduino-ide-extension/src/browser/serial/plotter/plotter-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/serial/plotter/plotter-frontend-contribution.ts @@ -45,7 +45,7 @@ export class PlotterFrontendContribution extends Contribution { @inject(BoardsServiceProvider) protected readonly boardsServiceProvider: BoardsServiceProvider; - onStart(app: FrontendApplication): MaybePromise { + override onStart(app: FrontendApplication): MaybePromise { this.url = new Endpoint({ path: '/plotter' }).getRestUrl().toString(); ipcRenderer.on('CLOSE_CHILD_WINDOW', async () => { @@ -56,13 +56,13 @@ export class PlotterFrontendContribution extends Contribution { return super.onStart(app); } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(SerialPlotterContribution.Commands.OPEN, { execute: this.connect.bind(this), }); } - registerMenus(menus: MenuModelRegistry): void { + override registerMenus(menus: MenuModelRegistry): void { menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, { commandId: SerialPlotterContribution.Commands.OPEN.id, label: SerialPlotterContribution.Commands.OPEN.label, diff --git a/arduino-ide-extension/src/browser/theia/core/application-shell.ts b/arduino-ide-extension/src/browser/theia/core/application-shell.ts index 8af61bdf2..b7423c577 100644 --- a/arduino-ide-extension/src/browser/theia/core/application-shell.ts +++ b/arduino-ide-extension/src/browser/theia/core/application-shell.ts @@ -33,7 +33,7 @@ export class ApplicationShell extends TheiaApplicationShell { @inject(ConnectionStatusService) protected readonly connectionStatusService: ConnectionStatusService; - protected track(widget: Widget): void { + protected override track(widget: Widget): void { super.track(widget); if (widget instanceof OutputWidget) { widget.title.closable = false; // TODO: https://arduino.slack.com/archives/C01698YT7S4/p1598011990133700 @@ -61,7 +61,7 @@ export class ApplicationShell extends TheiaApplicationShell { return false; } - async addWidget( + override async addWidget( widget: Widget, options: Readonly = {} ): Promise { @@ -87,19 +87,19 @@ export class ApplicationShell extends TheiaApplicationShell { return super.addWidget(widget, { ...options, ref }); } - handleEvent(): boolean { + override handleEvent(): boolean { // NOOP, dragging has been disabled - return false + return false; } // Avoid hiding top panel as we use it for arduino toolbar - protected createTopPanel(): Panel { + protected override createTopPanel(): Panel { const topPanel = super.createTopPanel(); topPanel.show(); return topPanel; } - async saveAll(): Promise { + override async saveAll(): Promise { if ( this.connectionStatusService.currentStatus === ConnectionStatus.OFFLINE ) { diff --git a/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts b/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts index 2898dd7c4..737ca98ac 100644 --- a/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts +++ b/arduino-ide-extension/src/browser/theia/core/browser-main-menu-factory.ts @@ -12,12 +12,12 @@ export class BrowserMainMenuFactory { protected menuBar: MenuBarWidget | undefined; - createMenuBar(): MenuBarWidget { + override createMenuBar(): MenuBarWidget { this.menuBar = super.createMenuBar(); return this.menuBar; } - update() { + update(): void { if (this.menuBar) { this.menuBar.clearMenus(); this.fillMenuBar(this.menuBar); diff --git a/arduino-ide-extension/src/browser/theia/core/browser-menu-plugin.ts b/arduino-ide-extension/src/browser/theia/core/browser-menu-plugin.ts index e82fd719e..ee234fbdb 100644 --- a/arduino-ide-extension/src/browser/theia/core/browser-menu-plugin.ts +++ b/arduino-ide-extension/src/browser/theia/core/browser-menu-plugin.ts @@ -4,7 +4,7 @@ import { BrowserMenuBarContribution } from '@theia/core/lib/browser/menu/browser @injectable() export class ArduinoMenuContribution extends BrowserMenuBarContribution { - onStart(app: FrontendApplication): void { + override onStart(app: FrontendApplication): void { const menu = this.factory.createMenuBar(); app.shell.addWidget(menu, { area: 'top' }); } diff --git a/arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts index 4687dfde3..8a0d30b5d 100644 --- a/arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/core/common-frontend-contribution.ts @@ -8,7 +8,7 @@ import { CommandRegistry } from '@theia/core/lib/common/command'; @injectable() export class CommonFrontendContribution extends TheiaCommonFrontendContribution { - registerCommands(commandRegistry: CommandRegistry): void { + override registerCommands(commandRegistry: CommandRegistry): void { super.registerCommands(commandRegistry); for (const command of [ @@ -26,7 +26,7 @@ export class CommonFrontendContribution extends TheiaCommonFrontendContribution } } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); for (const command of [ CommonCommands.SAVE, diff --git a/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts b/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts index 5117d2730..64a3e93a7 100644 --- a/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts +++ b/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts @@ -21,7 +21,7 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat protected isRunning = false; @postConstruct() - protected async init(): Promise { + protected override async init(): Promise { this.schedulePing(); try { this.isRunning = await this.daemon.isRunning(); @@ -54,14 +54,14 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon this.notificationCenter.onDaemonStopped(() => (this.isRunning = false)); } - protected onStateChange(state: ConnectionStatus): void { + protected override onStateChange(state: ConnectionStatus): void { if (!this.isRunning && state === ConnectionStatus.ONLINE) { return; } super.onStateChange(state); } - protected handleOffline(): void { + protected override handleOffline(): void { this.statusBar.setElement('connection-status', { alignment: StatusBarAlignment.LEFT, text: this.isRunning diff --git a/arduino-ide-extension/src/browser/theia/core/frontend-application.ts b/arduino-ide-extension/src/browser/theia/core/frontend-application.ts index 9c5234c46..766ef1bb0 100644 --- a/arduino-ide-extension/src/browser/theia/core/frontend-application.ts +++ b/arduino-ide-extension/src/browser/theia/core/frontend-application.ts @@ -20,7 +20,7 @@ export class FrontendApplication extends TheiaFrontendApplication { @inject(SketchesService) protected readonly sketchesService: SketchesService; - protected async initializeLayout(): Promise { + protected override async initializeLayout(): Promise { await super.initializeLayout(); const roots = await this.workspaceService.roots; for (const root of roots) { @@ -35,7 +35,9 @@ export class FrontendApplication extends TheiaFrontendApplication { } } - protected getStartupIndicator(host: HTMLElement): HTMLElement | undefined { + protected override getStartupIndicator( + host: HTMLElement + ): HTMLElement | undefined { let startupElement = this.doGetStartupIndicator(host, 'old-theia-preload'); // https://github.com/eclipse-theia/theia/pull/10761#issuecomment-1131476318 if (!startupElement) { startupElement = this.doGetStartupIndicator(host, 'theia-preload'); // We show the new Theia spinner in dev mode. diff --git a/arduino-ide-extension/src/browser/theia/core/tab-bar-decorator.ts b/arduino-ide-extension/src/browser/theia/core/tab-bar-decorator.ts index ecf9199d0..ea1f29eed 100644 --- a/arduino-ide-extension/src/browser/theia/core/tab-bar-decorator.ts +++ b/arduino-ide-extension/src/browser/theia/core/tab-bar-decorator.ts @@ -27,7 +27,7 @@ export class TabBarDecoratorService extends TheiaTabBarDecoratorService { ); } - getDecorations(title: Title): WidgetDecoration.Data[] { + override getDecorations(title: Title): WidgetDecoration.Data[] { if (title.owner instanceof EditorWidget) { const editor = title.owner.editor; if (this.dataDirUri && this.dataDirUri.isEqualOrParent(editor.uri)) { diff --git a/arduino-ide-extension/src/browser/theia/core/tab-bar-toolbar.tsx b/arduino-ide-extension/src/browser/theia/core/tab-bar-toolbar.tsx index a57b658ba..42e086d2b 100644 --- a/arduino-ide-extension/src/browser/theia/core/tab-bar-toolbar.tsx +++ b/arduino-ide-extension/src/browser/theia/core/tab-bar-toolbar.tsx @@ -12,7 +12,7 @@ export class TabBarToolbar extends TheiaTabBarToolbar { * Copied over from Theia. Added an ID to the parent of the toolbar item (`--container`). * CSS3 does not support parent selectors but we want to style the parent of the toolbar item. */ - protected renderItem(item: TabBarToolbarItem): React.ReactNode { + protected override renderItem(item: TabBarToolbarItem): React.ReactNode { let innerText = ''; const classNames = []; if (item.text) { diff --git a/arduino-ide-extension/src/browser/theia/core/tab-bars.ts b/arduino-ide-extension/src/browser/theia/core/tab-bars.ts index 03a518c70..c6adbc236 100644 --- a/arduino-ide-extension/src/browser/theia/core/tab-bars.ts +++ b/arduino-ide-extension/src/browser/theia/core/tab-bars.ts @@ -3,7 +3,7 @@ import { Saveable } from '@theia/core/lib/browser/saveable'; import { TabBarRenderer as TheiaTabBarRenderer } from '@theia/core/lib/browser/shell/tab-bars'; export class TabBarRenderer extends TheiaTabBarRenderer { - createTabClass(data: TabBar.IRenderData): string { + override createTabClass(data: TabBar.IRenderData): string { let className = super.createTabClass(data); if (!data.title.closable && Saveable.isDirty(data.title.owner)) { className += ' p-mod-closable'; diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts b/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts index dc3be2836..ebe4c5c3e 100644 --- a/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts +++ b/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts @@ -36,7 +36,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager { } @postConstruct() - protected async init(): Promise { + protected override async init(): Promise { super.init(); this.appStateService.reachedState('ready').then(async () => { const tempContent = await this.getTempLaunchJsonContent(); @@ -73,7 +73,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager { }); } - protected updateModels = debounce(async () => { + protected override updateModels = debounce(async () => { await this.appStateService.reachedState('ready'); const roots = await this.workspaceService.roots; const toDelete = new Set(this.models.keys()); diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-configuration-model.ts b/arduino-ide-extension/src/browser/theia/debug/debug-configuration-model.ts index f1ccf01d1..225a003c1 100644 --- a/arduino-ide-extension/src/browser/theia/debug/debug-configuration-model.ts +++ b/arduino-ide-extension/src/browser/theia/debug/debug-configuration-model.ts @@ -6,8 +6,8 @@ import { DebugConfigurationModel as TheiaDebugConfigurationModel } from '@theia/ export class DebugConfigurationModel extends TheiaDebugConfigurationModel { constructor( - readonly workspaceFolderUri: string, - protected readonly preferences: PreferenceService, + override readonly workspaceFolderUri: string, + protected override readonly preferences: PreferenceService, protected readonly config: DebugConfiguration[], protected configUri: URI | undefined, protected readonly onConfigDidChange: Event @@ -25,7 +25,7 @@ export class DebugConfigurationModel extends TheiaDebugConfigurationModel { this.reconcile(); } - protected parseConfigurations(): TheiaDebugConfigurationModel.JsonContent { + protected override parseConfigurations(): TheiaDebugConfigurationModel.JsonContent { return { uri: this.configUri, configurations: this.config, diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts b/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts index 1060b112c..00e351ece 100644 --- a/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts @@ -13,7 +13,7 @@ export class DebugFrontendApplicationContribution extends TheiaDebugFrontendAppl this.options.defaultWidgetOptions.rank = 4; } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); unregisterSubmenu(DebugMenus.DEBUG, registry); } diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-hover-source.ts b/arduino-ide-extension/src/browser/theia/debug/debug-hover-source.ts deleted file mode 100644 index 14c5a3d9b..000000000 --- a/arduino-ide-extension/src/browser/theia/debug/debug-hover-source.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { injectable } from '@theia/core/shared/inversify'; -import { - ExpressionItem, - DebugVariable, -} from '@theia/debug/lib/browser/console/debug-console-items'; -import { DebugHoverSource as TheiaDebugHoverSource } from '@theia/debug/lib/browser/editor/debug-hover-source'; - -// TODO: remove after https://github.com/eclipse-theia/theia/pull/9256/. -@injectable() -export class DebugHoverSource extends TheiaDebugHoverSource { - async evaluate2( - expression: string - ): Promise { - const evaluated = await this.doEvaluate(expression); - const elements = evaluated && (await evaluated.getElements()); - this._expression = evaluated; - this.elements = elements ? [...elements] : []; - this.fireDidChange(); - return evaluated; - } -} diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-hover-widget.ts b/arduino-ide-extension/src/browser/theia/debug/debug-hover-widget.ts deleted file mode 100644 index 437555bdb..000000000 --- a/arduino-ide-extension/src/browser/theia/debug/debug-hover-widget.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { injectable, interfaces, Container } from '@theia/core/shared/inversify'; -import { Widget } from '@theia/core/shared/@phosphor/widgets'; -import { SourceTreeWidget } from '@theia/core/lib/browser/source-tree'; -import { DisposableCollection } from '@theia/core/lib/common/disposable'; -import { DebugEditor } from '@theia/debug/lib/browser/editor/debug-editor'; -import { DebugVariable } from '@theia/debug/lib/browser/console/debug-console-items'; -import { DebugExpressionProvider } from '@theia/debug/lib/browser/editor/debug-expression-provider'; -import { DebugHoverSource as TheiaDebugHoverSource } from '@theia/debug/lib/browser/editor/debug-hover-source'; -import { - DebugHoverWidget as TheiaDebugHoverWidget, - ShowDebugHoverOptions, -} from '@theia/debug/lib/browser/editor/debug-hover-widget'; -import { DebugHoverSource } from './debug-hover-source'; - -export function createDebugHoverWidgetContainer( - parent: interfaces.Container, - editor: DebugEditor -): Container { - const child = SourceTreeWidget.createContainer(parent, { - virtualized: false, - }); - child.bind(DebugEditor).toConstantValue(editor); - child.bind(TheiaDebugHoverSource).toSelf(); - child.bind(DebugHoverSource).toSelf(); - child.rebind(TheiaDebugHoverSource).to(DebugHoverSource); - child.unbind(SourceTreeWidget); - child.bind(DebugExpressionProvider).toSelf(); - child.bind(TheiaDebugHoverWidget).toSelf(); - child.bind(DebugHoverWidget).toSelf(); - child.rebind(TheiaDebugHoverWidget).to(DebugHoverWidget); - return child; -} - -// TODO: remove patch after https://github.com/eclipse-theia/theia/pull/9256/ -@injectable() -export class DebugHoverWidget extends TheiaDebugHoverWidget { - protected async doShow( - options: ShowDebugHoverOptions | undefined = this.options - ): Promise { - if (!this.isEditorFrame()) { - this.hide(); - return; - } - if (!options) { - this.hide(); - return; - } - if (this.options && this.options.selection.equalsRange(options.selection)) { - return; - } - if (!this.isAttached) { - Widget.attach(this, this.contentNode); - } - - this.options = options; - const matchingExpression = this.expressionProvider.get( - this.editor.getControl().getModel()!, - options.selection - ); - if (!matchingExpression) { - this.hide(); - return; - } - const toFocus = new DisposableCollection(); - if (this.options.focus === true) { - toFocus.push( - this.model.onNodeRefreshed(() => { - toFocus.dispose(); - this.activate(); - }) - ); - } - const expression = await (this.hoverSource as DebugHoverSource).evaluate2( - matchingExpression - ); - if (!expression || !expression.value) { - toFocus.dispose(); - this.hide(); - return; - } - - this.contentNode.hidden = false; - ['number', 'boolean', 'string'].forEach((token) => - this.titleNode.classList.remove(token) - ); - this.domNode.classList.remove('complex-value'); - if (expression.hasElements) { - this.domNode.classList.add('complex-value'); - } else { - this.contentNode.hidden = true; - if ( - expression.type === 'number' || - expression.type === 'boolean' || - expression.type === 'string' - ) { - this.titleNode.classList.add(expression.type); - } else if (!isNaN(+expression.value)) { - this.titleNode.classList.add('number'); - } else if (DebugVariable.booleanRegex.test(expression.value)) { - this.titleNode.classList.add('boolean'); - } else if (DebugVariable.stringRegex.test(expression.value)) { - this.titleNode.classList.add('string'); - } - } - - // super.show(); // Here we cannot call `super.show()` but have to call `show` on the `Widget` prototype. - Widget.prototype.show.call(this); - await new Promise((resolve) => { - setTimeout( - () => - window.requestAnimationFrame(() => { - this.editor.getControl().layoutContentWidget(this); - resolve(); - }), - 0 - ); - }); - } -} diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-session-manager.ts b/arduino-ide-extension/src/browser/theia/debug/debug-session-manager.ts index 16345af8c..6eb2ebdeb 100644 --- a/arduino-ide-extension/src/browser/theia/debug/debug-session-manager.ts +++ b/arduino-ide-extension/src/browser/theia/debug/debug-session-manager.ts @@ -7,7 +7,7 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class DebugSessionManager extends TheiaDebugSessionManager { - async start(options: DebugSessionOptions): Promise { + override async start(options: DebugSessionOptions): Promise { return this.progressService.withProgress( nls.localize('theia/debug/start', 'Start...'), 'debug', @@ -76,7 +76,7 @@ export class DebugSessionManager extends TheiaDebugSessionManager { } ); } - async terminateSession(session?: DebugSession): Promise { + override async terminateSession(session?: DebugSession): Promise { if (!session) { this.updateCurrentSession(this._currentSession); session = this._currentSession; diff --git a/arduino-ide-extension/src/browser/theia/dialogs/dialogs.ts b/arduino-ide-extension/src/browser/theia/dialogs/dialogs.ts index ab479cf13..b93131c7f 100644 --- a/arduino-ide-extension/src/browser/theia/dialogs/dialogs.ts +++ b/arduino-ide-extension/src/browser/theia/dialogs/dialogs.ts @@ -8,7 +8,7 @@ import { @injectable() export abstract class AbstractDialog extends TheiaAbstractDialog { - constructor(@inject(DialogProps) protected readonly props: DialogProps) { + constructor(@inject(DialogProps) protected override readonly props: DialogProps) { super(props); this.closeCrossNode.classList.remove(...codiconArray('close')); diff --git a/arduino-ide-extension/src/browser/theia/editor/editor-command.ts b/arduino-ide-extension/src/browser/theia/editor/editor-command.ts index 5b98de336..9f4a3ffc5 100644 --- a/arduino-ide-extension/src/browser/theia/editor/editor-command.ts +++ b/arduino-ide-extension/src/browser/theia/editor/editor-command.ts @@ -4,7 +4,7 @@ import { EditorCommandContribution as TheiaEditorCommandContribution } from '@th @injectable() export class EditorCommandContribution extends TheiaEditorCommandContribution { @postConstruct() - protected init(): void { + protected override init(): void { // Workaround for https://github.com/eclipse-theia/theia/issues/8722. this.editorPreferences.onPreferenceChanged( ({ preferenceName, newValue, oldValue }) => { diff --git a/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts b/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts index be497e688..25a790b4c 100644 --- a/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts +++ b/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts @@ -16,9 +16,9 @@ export class EditorWidgetFactory extends TheiaEditorWidgetFactory { protected readonly sketchesServiceClient: SketchesServiceClientImpl; @inject(LabelProvider) - protected readonly labelProvider: LabelProvider; + protected override readonly labelProvider: LabelProvider; - protected async createEditor(uri: URI): Promise { + protected override async createEditor(uri: URI): Promise { const widget = await super.createEditor(uri); return this.maybeUpdateCaption(widget); } diff --git a/arduino-ide-extension/src/browser/theia/keymaps/keymaps-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/keymaps/keymaps-frontend-contribution.ts index d993c70e6..13914d025 100644 --- a/arduino-ide-extension/src/browser/theia/keymaps/keymaps-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/keymaps/keymaps-frontend-contribution.ts @@ -9,7 +9,7 @@ import { nls } from '@theia/core/lib/common'; @injectable() export class KeymapsFrontendContribution extends TheiaKeymapsFrontendContribution { - registerMenus(menus: MenuModelRegistry): void { + override registerMenus(menus: MenuModelRegistry): void { menus.registerMenuAction(ArduinoMenus.FILE__ADVANCED_SUBMENU, { commandId: KeymapsCommands.OPEN_KEYMAPS.id, label: nls.localize( diff --git a/arduino-ide-extension/src/browser/theia/markers/problem-contribution.ts b/arduino-ide-extension/src/browser/theia/markers/problem-contribution.ts index c837f5b73..d10f6adba 100644 --- a/arduino-ide-extension/src/browser/theia/markers/problem-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/markers/problem-contribution.ts @@ -6,15 +6,15 @@ import { ProblemContribution as TheiaProblemContribution } from '@theia/markers/ @injectable() export class ProblemContribution extends TheiaProblemContribution { - async initializeLayout(app: FrontendApplication): Promise { + override async initializeLayout(app: FrontendApplication): Promise { // NOOP } - protected setStatusBarElement(problemStat: ProblemStat): void { + protected override setStatusBarElement(problemStat: ProblemStat): void { // NOOP } - registerKeybindings(keybindings: KeybindingRegistry): void { + override registerKeybindings(keybindings: KeybindingRegistry): void { if (this.toggleCommand) { keybindings.registerKeybinding({ command: this.toggleCommand.id, diff --git a/arduino-ide-extension/src/browser/theia/markers/problem-manager.ts b/arduino-ide-extension/src/browser/theia/markers/problem-manager.ts index 3b3912464..0e830fd54 100644 --- a/arduino-ide-extension/src/browser/theia/markers/problem-manager.ts +++ b/arduino-ide-extension/src/browser/theia/markers/problem-manager.ts @@ -17,7 +17,7 @@ export class ProblemManager extends TheiaProblemManager { protected dataDirUri: URI | undefined; @postConstruct() - protected init(): void { + protected override init(): void { super.init(); this.configService .getConfiguration() @@ -27,7 +27,7 @@ export class ProblemManager extends TheiaProblemManager { ); } - setMarkers( + override setMarkers( uri: URI, owner: string, data: Diagnostic[] diff --git a/arduino-ide-extension/src/browser/theia/messages/notification-center-component.tsx b/arduino-ide-extension/src/browser/theia/messages/notification-center-component.tsx index 0e3bc4d52..b4b83bc77 100644 --- a/arduino-ide-extension/src/browser/theia/messages/notification-center-component.tsx +++ b/arduino-ide-extension/src/browser/theia/messages/notification-center-component.tsx @@ -7,7 +7,7 @@ import { codicon } from '@theia/core/lib/browser'; const PerfectScrollbar = require('react-perfect-scrollbar'); export class NotificationCenterComponent extends TheiaNotificationCenterComponent { - render(): React.ReactNode { + override render(): React.ReactNode { const empty = this.state.notifications.length === 0; const title = empty ? nls.localize( diff --git a/arduino-ide-extension/src/browser/theia/messages/notification-component.tsx b/arduino-ide-extension/src/browser/theia/messages/notification-component.tsx index 9eaca094c..18b967836 100644 --- a/arduino-ide-extension/src/browser/theia/messages/notification-component.tsx +++ b/arduino-ide-extension/src/browser/theia/messages/notification-component.tsx @@ -4,7 +4,7 @@ import { nls } from '@theia/core/lib/common'; import { codicon } from '@theia/core/lib/browser'; export class NotificationComponent extends TheiaNotificationComponent { - render(): React.ReactNode { + override render(): React.ReactNode { const { messageId, message, type, collapsed, expandable, source, actions } = this.props.notification; return ( diff --git a/arduino-ide-extension/src/browser/theia/messages/notification-toasts-component.tsx b/arduino-ide-extension/src/browser/theia/messages/notification-toasts-component.tsx index 6f46c8e49..393dd9b5a 100644 --- a/arduino-ide-extension/src/browser/theia/messages/notification-toasts-component.tsx +++ b/arduino-ide-extension/src/browser/theia/messages/notification-toasts-component.tsx @@ -3,7 +3,7 @@ import { NotificationComponent } from './notification-component'; import { NotificationToastsComponent as TheiaNotificationToastsComponent } from '@theia/messages/lib/browser/notification-toasts-component'; export class NotificationToastsComponent extends TheiaNotificationToastsComponent { - render(): React.ReactNode { + override render(): React.ReactNode { return (
{ diff --git a/arduino-ide-extension/src/browser/theia/monaco/monaco-status-bar-contribution.ts b/arduino-ide-extension/src/browser/theia/monaco/monaco-status-bar-contribution.ts index fa7ee0673..fca883087 100644 --- a/arduino-ide-extension/src/browser/theia/monaco/monaco-status-bar-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/monaco/monaco-status-bar-contribution.ts @@ -3,7 +3,7 @@ import { MonacoStatusBarContribution as TheiaMonacoStatusBarContribution } from @injectable() export class MonacoStatusBarContribution extends TheiaMonacoStatusBarContribution { - protected setConfigTabSizeWidget() {} + protected override setConfigTabSizeWidget() {} - protected setLineEndingWidget() {} + protected override setLineEndingWidget() {} } diff --git a/arduino-ide-extension/src/browser/theia/monaco/monaco-text-model-service.ts b/arduino-ide-extension/src/browser/theia/monaco/monaco-text-model-service.ts index a7a36adc0..7a8ece561 100644 --- a/arduino-ide-extension/src/browser/theia/monaco/monaco-text-model-service.ts +++ b/arduino-ide-extension/src/browser/theia/monaco/monaco-text-model-service.ts @@ -13,7 +13,7 @@ export class MonacoTextModelService extends TheiaMonacoTextModelService { @inject(SketchesServiceClientImpl) protected readonly sketchesServiceClient: SketchesServiceClientImpl; - protected async createModel(resource: Resource): Promise { + protected override async createModel(resource: Resource): Promise { const factory = this.factories .getContributions() .find(({ scheme }) => resource.uri.scheme === scheme); @@ -33,7 +33,7 @@ export class MonacoTextModelService extends TheiaMonacoTextModelService { // https://github.com/eclipse-theia/theia/pull/8491 class SilentMonacoEditorModel extends MonacoEditorModel { - protected trace(loggable: Loggable): void { + protected override trace(loggable: Loggable): void { if (this.logger) { this.logger.trace((log: Log) => loggable((message, ...params) => @@ -46,24 +46,24 @@ class SilentMonacoEditorModel extends MonacoEditorModel { class MaybeReadonlyMonacoEditorModel extends SilentMonacoEditorModel { constructor( - protected readonly resource: Resource, - protected readonly m2p: MonacoToProtocolConverter, - protected readonly p2m: ProtocolToMonacoConverter, - protected readonly logger?: ILogger, - protected readonly editorPreferences?: EditorPreferences, + protected override readonly resource: Resource, + protected override readonly m2p: MonacoToProtocolConverter, + protected override readonly p2m: ProtocolToMonacoConverter, + protected override readonly logger?: ILogger, + protected override readonly editorPreferences?: EditorPreferences, protected readonly _readOnly?: boolean ) { super(resource, m2p, p2m, logger, editorPreferences); } - get readOnly(): boolean { + override get readOnly(): boolean { if (typeof this._readOnly === 'boolean') { return this._readOnly; } return this.resource.saveContents === undefined; } - protected setDirty(dirty: boolean): void { + protected override setDirty(dirty: boolean): void { if (this._readOnly === true) { // NOOP return; diff --git a/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts b/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts index 86207b82a..23d46aaa1 100644 --- a/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts @@ -13,14 +13,14 @@ import { WorkspacePreferences } from '@theia/workspace/lib/browser/workspace-pre export class FileNavigatorContribution extends TheiaFileNavigatorContribution { constructor( @inject(FileNavigatorPreferences) - protected readonly fileNavigatorPreferences: FileNavigatorPreferences, - @inject(OpenerService) protected readonly openerService: OpenerService, + protected override readonly fileNavigatorPreferences: FileNavigatorPreferences, + @inject(OpenerService) protected override readonly openerService: OpenerService, @inject(FileNavigatorFilter) - protected readonly fileNavigatorFilter: FileNavigatorFilter, + protected override readonly fileNavigatorFilter: FileNavigatorFilter, @inject(WorkspaceService) - protected readonly workspaceService: WorkspaceService, + protected override readonly workspaceService: WorkspaceService, @inject(WorkspacePreferences) - protected readonly workspacePreferences: WorkspacePreferences + protected override readonly workspacePreferences: WorkspacePreferences ) { super( fileNavigatorPreferences, @@ -32,11 +32,11 @@ export class FileNavigatorContribution extends TheiaFileNavigatorContribution { this.options.defaultWidgetOptions.rank = 1; } - async initializeLayout(app: FrontendApplication): Promise { + override async initializeLayout(app: FrontendApplication): Promise { // NOOP } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { super.registerKeybindings(registry); [WorkspaceCommands.FILE_RENAME, WorkspaceCommands.FILE_DELETE].forEach( registry.unregisterKeybinding.bind(registry) diff --git a/arduino-ide-extension/src/browser/theia/navigator/navigator-tab-bar-decorator.ts b/arduino-ide-extension/src/browser/theia/navigator/navigator-tab-bar-decorator.ts index d046f1cfc..b5b791bc4 100644 --- a/arduino-ide-extension/src/browser/theia/navigator/navigator-tab-bar-decorator.ts +++ b/arduino-ide-extension/src/browser/theia/navigator/navigator-tab-bar-decorator.ts @@ -8,11 +8,11 @@ import { NavigatorTabBarDecorator as TheiaNavigatorTabBarDecorator } from '@thei */ @injectable() export class NavigatorTabBarDecorator extends TheiaNavigatorTabBarDecorator { - onStart(): void { + override onStart(): void { // NOOP } - decorate(): WidgetDecoration.Data[] { + override decorate(): WidgetDecoration.Data[] { // Does not decorate anything. return []; } diff --git a/arduino-ide-extension/src/browser/theia/outline/outline-contribution.ts b/arduino-ide-extension/src/browser/theia/outline/outline-contribution.ts index 6dc60aba5..c0232d395 100644 --- a/arduino-ide-extension/src/browser/theia/outline/outline-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/outline/outline-contribution.ts @@ -12,7 +12,7 @@ export class OutlineViewContribution extends TheiaOutlineViewContribution { }; } - async initializeLayout(app: FrontendApplication): Promise { + override async initializeLayout(app: FrontendApplication): Promise { // NOOP } } diff --git a/arduino-ide-extension/src/browser/theia/output/output-channel.ts b/arduino-ide-extension/src/browser/theia/output/output-channel.ts index 15b9daff3..b928dce06 100644 --- a/arduino-ide-extension/src/browser/theia/output/output-channel.ts +++ b/arduino-ide-extension/src/browser/theia/output/output-channel.ts @@ -11,7 +11,7 @@ import { @injectable() export class OutputChannelManager extends TheiaOutputChannelManager { - getChannel(name: string): TheiaOutputChannel { + override getChannel(name: string): TheiaOutputChannel { const existing = this.channels.get(name); if (existing) { return existing; @@ -43,7 +43,7 @@ export class OutputChannelManager extends TheiaOutputChannelManager { } export class OutputChannel extends TheiaOutputChannel { - dispose(): void { + override dispose(): void { super.dispose(); if ((this as any).disposed) { const textModifyQueue: PQueue = (this as any).textModifyQueue; diff --git a/arduino-ide-extension/src/browser/theia/output/output-toolbar-contribution.ts b/arduino-ide-extension/src/browser/theia/output/output-toolbar-contribution.ts index 91971e3b5..cf0e524a6 100644 --- a/arduino-ide-extension/src/browser/theia/output/output-toolbar-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/output/output-toolbar-contribution.ts @@ -8,7 +8,7 @@ import { OutputToolbarContribution as TheiaOutputToolbarContribution } from '@th @injectable() export class OutputToolbarContribution extends TheiaOutputToolbarContribution { - async registerToolbarItems(registry: TabBarToolbarRegistry): Promise { + override async registerToolbarItems(registry: TabBarToolbarRegistry): Promise { await super.registerToolbarItems(registry); // Why is it async? // It's a hack. Currently, it's not possible to unregister a toolbar contribution via API. ( diff --git a/arduino-ide-extension/src/browser/theia/output/output-widget.ts b/arduino-ide-extension/src/browser/theia/output/output-widget.ts index a975e6a5b..6d6b684d0 100644 --- a/arduino-ide-extension/src/browser/theia/output/output-widget.ts +++ b/arduino-ide-extension/src/browser/theia/output/output-widget.ts @@ -6,7 +6,7 @@ import { OutputWidget as TheiaOutputWidget } from '@theia/output/lib/browser/out // Remove this module after ATL-222 and the Theia update. @injectable() export class OutputWidget extends TheiaOutputWidget { - protected onAfterShow(msg: Message): void { + protected override onAfterShow(msg: Message): void { super.onAfterShow(msg); this.onResize(Widget.ResizeMessage.UnknownSize); } diff --git a/arduino-ide-extension/src/browser/theia/plugin-ext/output-channel-registry-main.ts b/arduino-ide-extension/src/browser/theia/plugin-ext/output-channel-registry-main.ts index 09a79cf3f..1a5bdf12c 100644 --- a/arduino-ide-extension/src/browser/theia/plugin-ext/output-channel-registry-main.ts +++ b/arduino-ide-extension/src/browser/theia/plugin-ext/output-channel-registry-main.ts @@ -7,9 +7,9 @@ import { OutputChannelRegistryMainImpl as TheiaOutputChannelRegistryMainImpl } f @injectable() export class OutputChannelRegistryMainImpl extends TheiaOutputChannelRegistryMainImpl { @inject(CommandService) - protected readonly commandService: CommandService; + protected override readonly commandService: CommandService; - $append( + override $append( name: string, text: string, pluginInfo: PluginInfo @@ -21,17 +21,17 @@ export class OutputChannelRegistryMainImpl extends TheiaOutputChannelRegistryMai return Promise.resolve(); } - $clear(name: string): PromiseLike { + override $clear(name: string): PromiseLike { this.commandService.executeCommand(OutputCommands.CLEAR.id, { name }); return Promise.resolve(); } - $dispose(name: string): PromiseLike { + override $dispose(name: string): PromiseLike { this.commandService.executeCommand(OutputCommands.DISPOSE.id, { name }); return Promise.resolve(); } - async $reveal(name: string, preserveFocus: boolean): Promise { + override async $reveal(name: string, preserveFocus: boolean): Promise { const options = { preserveFocus }; this.commandService.executeCommand(OutputCommands.SHOW.id, { name, @@ -39,7 +39,7 @@ export class OutputChannelRegistryMainImpl extends TheiaOutputChannelRegistryMai }); } - $close(name: string): PromiseLike { + override $close(name: string): PromiseLike { this.commandService.executeCommand(OutputCommands.HIDE.id, { name }); return Promise.resolve(); } diff --git a/arduino-ide-extension/src/browser/theia/preferences/preferences-contribution.ts b/arduino-ide-extension/src/browser/theia/preferences/preferences-contribution.ts index 4fdd770b3..4aaf87e97 100644 --- a/arduino-ide-extension/src/browser/theia/preferences/preferences-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/preferences/preferences-contribution.ts @@ -6,7 +6,7 @@ import { PreferencesContribution as TheiaPreferencesContribution } from '@theia/ @injectable() export class PreferencesContribution extends TheiaPreferencesContribution { - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); // The settings group: preferences, CLI config is not part of the `File` menu on macOS. // On Windows and Linux, we rebind it to `Preferences...`. It is safe to remove here. @@ -16,7 +16,7 @@ export class PreferencesContribution extends TheiaPreferencesContribution { ); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { registry.unregisterKeybinding(CommonCommands.OPEN_PREFERENCES.id); } } diff --git a/arduino-ide-extension/src/browser/theia/scm/scm-contribution.ts b/arduino-ide-extension/src/browser/theia/scm/scm-contribution.ts index 47cad0ea9..cc759db5b 100644 --- a/arduino-ide-extension/src/browser/theia/scm/scm-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/scm/scm-contribution.ts @@ -4,11 +4,11 @@ import { StatusBarEntry } from '@theia/core/lib/browser/status-bar/status-bar'; @injectable() export class ScmContribution extends TheiaScmContribution { - async initializeLayout(): Promise { + override async initializeLayout(): Promise { // NOOP } - protected setStatusBarEntry(id: string, entry: StatusBarEntry): void { + protected override setStatusBarEntry(id: string, entry: StatusBarEntry): void { // NOOP } } diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-factory.ts b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-factory.ts index 81d35d0be..34afd4d22 100644 --- a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-factory.ts +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-factory.ts @@ -8,7 +8,7 @@ import { @injectable() export class SearchInWorkspaceFactory extends TheiaSearchInWorkspaceFactory { - async createWidget(): Promise { + override async createWidget(): Promise { const viewContainer = await super.createWidget(); viewContainer.setTitleOptions({ ...SEARCH_VIEW_CONTAINER_TITLE_OPTIONS, diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts index cda7ebc23..2204848fa 100644 --- a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts @@ -13,12 +13,12 @@ export class SearchInWorkspaceFrontendContribution extends TheiaSearchInWorkspac this.options.defaultWidgetOptions.rank = 5; } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); registry.unregisterMenuAction(SearchInWorkspaceCommands.OPEN_SIW_WIDGET); } - registerKeybindings(keybindings: KeybindingRegistry): void { + override registerKeybindings(keybindings: KeybindingRegistry): void { super.registerKeybindings(keybindings); keybindings.unregisterKeybinding(SearchInWorkspaceCommands.OPEN_SIW_WIDGET); } diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts index 5362be736..e831cd402 100644 --- a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts @@ -11,7 +11,7 @@ import { MEMORY_TEXT } from '@theia/core/lib/common/resource'; */ @injectable() export class SearchInWorkspaceResultTreeWidget extends TheiaSearchInWorkspaceResultTreeWidget { - protected async createReplacePreview( + protected override async createReplacePreview( node: SearchInWorkspaceFileNode ): Promise { const fileUri = new URI(node.fileUri).withScheme('file'); diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx index 58c35f5f6..cae633024 100644 --- a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx @@ -9,12 +9,12 @@ import { SearchInWorkspaceWidget as TheiaSearchInWorkspaceWidget } from '@theia/ @injectable() export class SearchInWorkspaceWidget extends TheiaSearchInWorkspaceWidget { @postConstruct() - protected init(): void { + protected override init(): void { super.init(); this.title.iconClass = 'fa fa-arduino-search'; } - protected renderGlobField(kind: 'include' | 'exclude'): React.ReactNode { + protected override renderGlobField(kind: 'include' | 'exclude'): React.ReactNode { const currentValue = this.searchInWorkspaceOptions[kind]; const value = (currentValue && currentValue.join(', ')) || ''; return ( diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts index 34b64ab43..ba6ebdd09 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts @@ -28,7 +28,7 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut @inject(SketchesService) protected readonly sketchService: SketchesService; - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); registry.unregisterCommand(WorkspaceCommands.NEW_FILE); registry.registerCommand( @@ -75,7 +75,7 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut } } - protected async validateFileName( + protected override async validateFileName( name: string, parent: FileStat, recursive = false diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts index 47f93232e..2ad5ab669 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts @@ -10,7 +10,7 @@ export class WorkspaceDeleteHandler extends TheiaWorkspaceDeleteHandler { @inject(SketchesServiceClientImpl) protected readonly sketchesServiceClient: SketchesServiceClientImpl; - async execute(uris: URI[]): Promise { + override async execute(uris: URI[]): Promise { const sketch = await this.sketchesServiceClient.currentSketch(); if (!sketch) { return; diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-frontend-contribution.ts index 63f9eb034..4574fedfc 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-frontend-contribution.ts @@ -10,7 +10,7 @@ import { WorkspaceFrontendContribution as TheiaWorkspaceFrontendContribution } f @injectable() export class WorkspaceFrontendContribution extends TheiaWorkspaceFrontendContribution { - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); // TODO: instead of blacklisting commands to remove, it would be more robust to whitelist the ones we want to keep const commands = new Set(registry.commands); @@ -28,9 +28,9 @@ export class WorkspaceFrontendContribution extends TheiaWorkspaceFrontendContrib .forEach(registry.unregisterCommand.bind(registry)); } - registerMenus(_: MenuModelRegistry): void {} + override registerMenus(_: MenuModelRegistry): void {} - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { super.registerKeybindings(registry); [ WorkspaceCommands.NEW_FILE, @@ -44,7 +44,7 @@ export class WorkspaceFrontendContribution extends TheiaWorkspaceFrontendContrib @injectable() export class ArduinoFileMenuContribution extends FileMenuContribution { - registerMenus(_: MenuModelRegistry): void { + override registerMenus(_: MenuModelRegistry): void { // NOOP } } diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-input-dialog.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-input-dialog.ts index af5a99dbe..d70d7e27d 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-input-dialog.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-input-dialog.ts @@ -13,8 +13,8 @@ export class WorkspaceInputDialog extends TheiaWorkspaceInputDialog { constructor( @inject(WorkspaceInputDialogProps) - protected readonly props: WorkspaceInputDialogProps, - @inject(LabelProvider) protected readonly labelProvider: LabelProvider + protected override readonly props: WorkspaceInputDialogProps, + @inject(LabelProvider) protected override readonly labelProvider: LabelProvider ) { super(props, labelProvider); this.appendCloseButton( @@ -22,18 +22,18 @@ export class WorkspaceInputDialog extends TheiaWorkspaceInputDialog { ); } - protected appendParentPath(): void { + protected override appendParentPath(): void { // NOOP } - isValid(value: string, mode: DialogMode): MaybePromise { + override isValid(value: string, mode: DialogMode): MaybePromise { if (value !== '') { this.wasTouched = true; } return super.isValid(value, mode); } - protected setErrorMessage(error: DialogError): void { + protected override setErrorMessage(error: DialogError): void { if (this.acceptButton) { this.acceptButton.disabled = !DialogError.getResult(error); } diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 6adbe5a67..02f8213cc 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -31,10 +31,10 @@ export class WorkspaceService extends TheiaWorkspaceService { protected readonly configService: ConfigService; @inject(LabelProvider) - protected readonly labelProvider: LabelProvider; + protected override readonly labelProvider: LabelProvider; @inject(MessageService) - protected readonly messageService: MessageService; + protected override readonly messageService: MessageService; @inject(ApplicationServer) protected readonly applicationServer: ApplicationServer; @@ -64,7 +64,7 @@ export class WorkspaceService extends TheiaWorkspaceService { // Was copied from the Theia implementation. // Unlike the default behavior, IDE2 does not check the existence of the workspace before open. - protected async doGetDefaultWorkspaceUri(): Promise { + protected override async doGetDefaultWorkspaceUri(): Promise { // If an empty window is explicitly requested do not restore a previous workspace. // Note: `window.location.hash` includes leading "#" if non-empty. if (window.location.hash === `#${DEFAULT_WINDOW_HASH}`) { @@ -86,7 +86,7 @@ export class WorkspaceService extends TheiaWorkspaceService { } } - protected getDefaultWorkspaceUri(): Promise { + protected override getDefaultWorkspaceUri(): Promise { if (this.workspaceUri) { // Avoid creating a new sketch twice return this.workspaceUri; @@ -132,7 +132,7 @@ export class WorkspaceService extends TheiaWorkspaceService { return this.workspaceUri; } - protected openNewWindow(workspacePath: string): void { + protected override openNewWindow(workspacePath: string): void { const { boardsConfig } = this.boardsServiceProvider; const url = BoardsConfig.Config.setConfig( boardsConfig, @@ -171,7 +171,7 @@ export class WorkspaceService extends TheiaWorkspaceService { } } - protected formatTitle(title?: string): string { + protected override formatTitle(title?: string): string { const version = this.version ? ` ${this.version}` : ''; const name = `${this.applicationName} ${version}`; return title ? `${title} | ${name}` : name; diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts index a91949ba5..bb8f89050 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts @@ -12,14 +12,14 @@ export class WorkspaceVariableContribution extends TheiaWorkspaceVariableContrib protected currentSketch?: Sketch; @postConstruct() - protected init(): void { + protected override init(): void { this.sketchesServiceClient .currentSketch() .then() .then((sketch) => (this.currentSketch = sketch)); } - getResourceUri(): URI | undefined { + override getResourceUri(): URI | undefined { const resourceUri = super.getResourceUri(); // https://github.com/arduino/arduino-ide/issues/46 // `currentWidget` can be an editor representing a file outside of the workspace. The current sketch should be a fallback. diff --git a/arduino-ide-extension/src/browser/toolbar/arduino-toolbar-contribution.ts b/arduino-ide-extension/src/browser/toolbar/arduino-toolbar-contribution.ts index 9180be90e..09c125e9a 100644 --- a/arduino-ide-extension/src/browser/toolbar/arduino-toolbar-contribution.ts +++ b/arduino-ide-extension/src/browser/toolbar/arduino-toolbar-contribution.ts @@ -19,7 +19,7 @@ export class ArduinoToolbarContainer extends Widget { this.toolbars = toolbars; } - onAfterAttach(msg: Message) { + override onAfterAttach(msg: Message) { for (const toolbar of this.toolbars) { Widget.attach(toolbar, this.node); } diff --git a/arduino-ide-extension/src/browser/toolbar/arduino-toolbar.tsx b/arduino-ide-extension/src/browser/toolbar/arduino-toolbar.tsx index d4abffbb5..c1a656206 100644 --- a/arduino-ide-extension/src/browser/toolbar/arduino-toolbar.tsx +++ b/arduino-ide-extension/src/browser/toolbar/arduino-toolbar.tsx @@ -71,7 +71,7 @@ export class ArduinoToolbarComponent extends React.Component< ); }; - render(): React.ReactNode { + override render(): React.ReactNode { const tooltip = (
{this.state.tooltip} diff --git a/arduino-ide-extension/src/browser/widgets/arduino-select.tsx b/arduino-ide-extension/src/browser/widgets/arduino-select.tsx index bccc4cef6..4ee84e82a 100644 --- a/arduino-ide-extension/src/browser/widgets/arduino-select.tsx +++ b/arduino-ide-extension/src/browser/widgets/arduino-select.tsx @@ -9,7 +9,7 @@ export class ArduinoSelect extends Select { super(props); } - render(): React.ReactNode { + override render(): React.ReactNode { const controlHeight = 27; // from `monitor.css` -> `.serial-monitor-container .head` (`height: 27px;`) const styles: Styles = { control: (styles) => ({ diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx index cc10e34b1..9661c02fe 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-composite-widget.tsx @@ -43,7 +43,7 @@ export class CloudSketchbookCompositeWidget extends BaseWidget { return this.cloudSketchbookTreeWidget; } - protected onAfterAttach(message: Message): void { + protected override onAfterAttach(message: Message): void { super.onAfterAttach(message); Widget.attach(this.cloudSketchbookTreeWidget, this.compositeNode); ReactDOM.render( @@ -58,7 +58,7 @@ export class CloudSketchbookCompositeWidget extends BaseWidget { ); } - protected onResize(message: Widget.ResizeMessage): void { + protected override onResize(message: Widget.ResizeMessage): void { super.onResize(message); MessageLoop.sendMessage( this.cloudSketchbookTreeWidget, diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts index 163a45131..322cfb08b 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts @@ -149,7 +149,7 @@ export class CloudSketchbookContribution extends Contribution { protected readonly toDisposeBeforeNewContextMenu = new DisposableCollection(); - registerMenus(menus: MenuModelRegistry): void { + override registerMenus(menus: MenuModelRegistry): void { menus.registerMenuAction(ArduinoMenus.FILE__ADVANCED_SUBMENU, { commandId: CloudSketchbookCommands.TOGGLE_CLOUD_SKETCHBOOK.id, label: CloudSketchbookCommands.TOGGLE_CLOUD_SKETCHBOOK.label, @@ -157,7 +157,7 @@ export class CloudSketchbookContribution extends Contribution { }); } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { registry.registerCommand(CloudSketchbookCommands.TOGGLE_CLOUD_SKETCHBOOK, { execute: () => { this.preferenceService.set( diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts index 708e2ec1b..d76c7497f 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-model.ts @@ -53,7 +53,7 @@ export function sketchesToFileStats(sketches: Create.Sketch[]): FileStat[] { @injectable() export class CloudSketchbookTreeModel extends SketchbookTreeModel { @inject(FileService) - protected readonly fileService: FileService; + protected override readonly fileService: FileService; @inject(AuthenticationClientService) protected readonly authenticationService: AuthenticationClientService; @@ -65,7 +65,7 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel { protected readonly cloudSketchbookTree: CloudSketchbookTree; @inject(ArduinoPreferences) - protected readonly arduinoPreferences: ArduinoPreferences; + protected override readonly arduinoPreferences: ArduinoPreferences; @inject(LocalCacheFsProvider) protected readonly localCacheFsProvider: LocalCacheFsProvider; @@ -74,14 +74,14 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel { protected readonly sketchCache: SketchCache; @postConstruct() - protected init(): void { + protected override init(): void { super.init(); this.toDispose.push( this.authenticationService.onSessionDidChange(() => this.updateRoot()) ); } - async createRoot(): Promise { + override async createRoot(): Promise { const { session } = this.authenticationService; if (!session) { this.tree.root = undefined; @@ -108,7 +108,7 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel { return this.tree as CloudSketchbookTree; } - protected recursivelyFindSketchRoot(node: TreeNode): any { + protected override recursivelyFindSketchRoot(node: TreeNode): any { if (node && CloudSketchbookTree.CloudSketchDirNode.is(node)) { return node; } @@ -121,7 +121,7 @@ export class CloudSketchbookTreeModel extends SketchbookTreeModel { return false; } - async revealFile(uri: URI): Promise { + override async revealFile(uri: URI): Promise { // we use remote uris as keys for the tree // convert local URIs const remoteuri = this.localCacheFsProvider.from(uri); diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx index 523700aed..043dfea86 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree-widget.tsx @@ -28,18 +28,18 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget { protected readonly cloudSketchbookTree: CloudSketchbookTree; @postConstruct() - protected async init(): Promise { + protected override async init(): Promise { await super.init(); this.addClass('tree-container'); // Adds `height: 100%` to the tree. Otherwise you cannot see it. } - protected renderTree(model: TreeModel): React.ReactNode { + protected override renderTree(model: TreeModel): React.ReactNode { if (this.shouldShowWelcomeView()) return this.renderViewWelcome(); if (this.shouldShowEmptyView()) return this.renderEmptyView(); return super.renderTree(model); } - protected renderEmptyView() { + protected renderEmptyView(): React.ReactNode { return (
@@ -71,7 +71,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget { ); } - protected shouldShowWelcomeView(): boolean { + protected override shouldShowWelcomeView(): boolean { if (!this.model || this.model instanceof CloudSketchbookTreeModel) { return !this.authenticationService.session; } @@ -83,7 +83,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget { return CompositeTreeNode.is(node) && node.children.length === 0; } - protected createNodeClassNames(node: any, props: NodeProps): string[] { + protected override createNodeClassNames(node: any, props: NodeProps): string[] { const classNames = super.createNodeClassNames(node, props); if ( @@ -97,7 +97,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget { return classNames; } - protected renderInlineCommands(node: any): React.ReactNode { + protected override renderInlineCommands(node: any): React.ReactNode { if (CloudSketchbookTree.CloudSketchDirNode.is(node) && node.commands) { return Array.from(new Set(node.commands)).map((command) => this.renderInlineCommand(command.id, node, { @@ -108,7 +108,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget { return undefined; } - protected renderViewWelcome(): React.ReactNode { + protected override renderViewWelcome(): React.ReactNode { return (
@@ -151,7 +151,7 @@ export class CloudSketchbookTreeWidget extends SketchbookTreeWidget { ); } - protected handleDblClickEvent( + protected override handleDblClickEvent( node: TreeNode, event: React.MouseEvent ): void { diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts index 4f4986bc2..7204df632 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-tree.ts @@ -47,7 +47,7 @@ type FilesToSync = { @injectable() export class CloudSketchbookTree extends SketchbookTree { @inject(FileService) - protected readonly fileService: FileService; + protected override readonly fileService: FileService; @inject(LocalCacheFsProvider) protected readonly localCacheFsProvider: LocalCacheFsProvider; @@ -56,7 +56,7 @@ export class CloudSketchbookTree extends SketchbookTree { protected readonly sketchCache: SketchCache; @inject(ArduinoPreferences) - protected readonly arduinoPreferences: ArduinoPreferences; + protected override readonly arduinoPreferences: ArduinoPreferences; @inject(PreferenceService) protected readonly preferenceService: PreferenceService; @@ -315,7 +315,7 @@ export class CloudSketchbookTree extends SketchbookTree { return { filesToWrite, filesToDelete }; } - async refresh( + override async refresh( node?: CompositeTreeNode ): Promise { if (node) { @@ -375,7 +375,7 @@ export class CloudSketchbookTree extends SketchbookTree { ); } - async resolveChildren(parent: CompositeTreeNode): Promise { + override async resolveChildren(parent: CompositeTreeNode): Promise { return (await super.resolveChildren(parent)).sort((a, b) => { if ( WorkspaceNode.is(parent) && @@ -403,12 +403,12 @@ export class CloudSketchbookTree extends SketchbookTree { } /** - * Retrieve fileStats for the given node, merging the local and remote childrens + * Retrieve fileStats for the given node, merging the local and remote children * Local children take precedence over remote ones * @param node * @returns */ - protected async resolveFileStat( + protected override async resolveFileStat( node: FileStatNode ): Promise { if ( @@ -470,7 +470,7 @@ export class CloudSketchbookTree extends SketchbookTree { } } - protected toNode( + protected override toNode( fileStat: any, parent: CompositeTreeNode ): FileNode | DirNode { @@ -529,7 +529,7 @@ export class CloudSketchbookTree extends SketchbookTree { * @param node * @returns */ - protected async augmentSketchNode(node: DirNode): Promise { + protected override async augmentSketchNode(node: DirNode): Promise { const sketch = this.sketchCache.getSketch( node.fileStat.resource.path.toString() ); @@ -582,7 +582,7 @@ export class CloudSketchbookTree extends SketchbookTree { return node; } - protected async decorateNode( + protected override async decorateNode( node: TreeNode, showAllFiles: boolean ): Promise { @@ -592,7 +592,7 @@ export class CloudSketchbookTree extends SketchbookTree { return node; } - protected async isSketchNode(node: DirNode): Promise { + protected override async isSketchNode(node: DirNode): Promise { if (DirNode.is(node)) { const sketch = this.sketchCache.getSketch( node.fileStat.resource.path.toString() diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts index 7cf71bfe9..22239a227 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-widget.ts @@ -12,11 +12,11 @@ export class CloudSketchbookWidget extends SketchbookWidget { protected readonly arduinoPreferences: ArduinoPreferences; @postConstruct() - protected init(): void { + protected override init(): void { super.init(); } - getTreeWidget(): any { + override getTreeWidget(): any { const widget: any = this.sketchbookTreesContainer.selectedWidgets().next(); if (widget && typeof widget.getTreeWidget !== 'undefined') { @@ -36,7 +36,7 @@ export class CloudSketchbookWidget extends SketchbookWidget { this.setDocumentMode(); } - setDocumentMode() { + setDocumentMode(): void { if (this.arduinoPreferences['arduino.cloud.enabled']) { this.sketchbookTreesContainer.mode = 'multiple-document'; } else { @@ -44,7 +44,7 @@ export class CloudSketchbookWidget extends SketchbookWidget { } } - protected onAfterAttach(msg: any) { + protected override onAfterAttach(msg: any): void { this.sketchbookTreesContainer.addWidget(this.widget); this.setDocumentMode(); this.arduinoPreferences.onPreferenceChanged((event) => { diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-user-status.tsx b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-user-status.tsx index 1157492ef..0db8dce92 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-user-status.tsx +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-user-status.tsx @@ -24,7 +24,7 @@ export class UserStatus extends React.Component< }; } - componentDidMount(): void { + override componentDidMount(): void { const statusListener = () => this.setState({ status: this.status }); window.addEventListener('online', statusListener); window.addEventListener('offline', statusListener); @@ -41,11 +41,11 @@ export class UserStatus extends React.Component< ]); } - componentWillUnmount(): void { + override componentWillUnmount(): void { this.toDispose.dispose(); } - render(): React.ReactNode { + override render(): React.ReactNode { if (!this.props.authenticationService.session) { return null; } diff --git a/arduino-ide-extension/src/browser/widgets/component-list/component-list-item.tsx b/arduino-ide-extension/src/browser/widgets/component-list/component-list-item.tsx index a0ebaf44d..39c0a2ce0 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/component-list-item.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/component-list-item.tsx @@ -43,7 +43,7 @@ export class ComponentListItem< this.setState({ selectedVersion: version }); } - render(): React.ReactNode { + override render(): React.ReactNode { const { item, itemRenderer } = this.props; return itemRenderer.renderItem( Object.assign(this.state, { item }), diff --git a/arduino-ide-extension/src/browser/widgets/component-list/component-list.tsx b/arduino-ide-extension/src/browser/widgets/component-list/component-list.tsx index 9b212cc2b..42dce70b8 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/component-list.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/component-list.tsx @@ -9,7 +9,7 @@ export class ComponentList extends React.Component< > { protected container?: HTMLElement; - render(): React.ReactNode { + override render(): React.ReactNode { return (
{this.props.items.map((item) => this.createItem(item))} @@ -17,7 +17,7 @@ export class ComponentList extends React.Component< ); } - componentDidMount(): void { + override componentDidMount(): void { if (this.container && this.props.resolveContainer) { this.props.resolveContainer(this.container); } diff --git a/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx b/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx index ee4882ba7..0fad3ac61 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/filterable-list-container.tsx @@ -28,19 +28,19 @@ export class FilterableListContainer< }; } - componentDidMount(): void { + override componentDidMount(): void { this.search = debounce(this.search, 500); this.handleFilterTextChange(''); this.props.filterTextChangeEvent(this.handleFilterTextChange.bind(this)); } - componentDidUpdate(): void { + override componentDidUpdate(): void { // See: arduino/arduino-pro-ide#101 // Resets the top of the perfect scroll-bar's thumb. this.props.container.updateScrollBar(); } - render(): React.ReactNode { + override render(): React.ReactNode { return (
{this.renderSearchFilter()} diff --git a/arduino-ide-extension/src/browser/widgets/component-list/list-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/widgets/component-list/list-widget-frontend-contribution.ts index 52e95a116..ed9827919 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/list-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/component-list/list-widget-frontend-contribution.ts @@ -11,7 +11,7 @@ export abstract class ListWidgetFrontendContribution { async initializeLayout(): Promise {} - registerMenus(): void { + override registerMenus(): void { // NOOP } } diff --git a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx index c19440d27..061562724 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx @@ -69,21 +69,21 @@ export abstract class ListWidget< ]); } - protected getScrollContainer(): MaybePromise { + protected override getScrollContainer(): MaybePromise { return this.deferredContainer.promise; } - protected onActivateRequest(message: Message): void { + protected override onActivateRequest(message: Message): void { super.onActivateRequest(message); (this.focusNode || this.node).focus(); } - protected onUpdateRequest(message: Message): void { + protected override onUpdateRequest(message: Message): void { super.onUpdateRequest(message); this.render(); } - protected onResize(message: Widget.ResizeMessage): void { + protected override onResize(message: Widget.ResizeMessage): void { super.onResize(message); this.updateScrollBar(); } diff --git a/arduino-ide-extension/src/browser/widgets/component-list/search-bar.tsx b/arduino-ide-extension/src/browser/widgets/component-list/search-bar.tsx index 81aeed196..cc9630989 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/search-bar.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/search-bar.tsx @@ -7,7 +7,7 @@ export class SearchBar extends React.Component { this.handleFilterTextChange = this.handleFilterTextChange.bind(this); } - render(): React.ReactNode { + override render(): React.ReactNode { return ( { + override *getNodesByUri(uri: URI): IterableIterator { const workspace = this.root; if (WorkspaceNode.is(workspace)) { for (const root of workspace.children) { @@ -183,7 +183,7 @@ export class SketchbookTreeModel extends FileTreeModel { /** * Move the given source file or directory to the given target directory. */ - async move(source: TreeNode, target: TreeNode): Promise { + override async move(source: TreeNode, target: TreeNode): Promise { if (source.parent && WorkspaceRootNode.is(source)) { // do not support moving a root folder return undefined; @@ -250,7 +250,7 @@ export class SketchbookTreeModel extends FileTreeModel { // selectNode gets called when the user single-clicks on an item // when this happens, we want to open the file if it belongs to the currently open sketch - async selectNode(node: Readonly): Promise { + override async selectNode(node: Readonly): Promise { super.selectNode(node); if (FileNode.is(node) && (await this.isFileInsideCurrentSketch(node))) { this.open(node.uri); @@ -264,7 +264,7 @@ export class SketchbookTreeModel extends FileTreeModel { }); } - protected async doOpenNode(node: TreeNode): Promise { + protected override async doOpenNode(node: TreeNode): Promise { // if it's a sketch dir, or a file from another sketch, open in new window if (!(await this.isFileInsideCurrentSketch(node))) { const sketchRoot = this.recursivelyFindSketchRoot(node); diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx index 4b1535216..0d7494545 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx @@ -33,10 +33,10 @@ export class SketchbookTreeWidget extends FileTreeWidget { protected currentSketchUri = ''; constructor( - @inject(TreeProps) readonly props: TreeProps, - @inject(SketchbookTreeModel) readonly model: SketchbookTreeModel, + @inject(TreeProps) override readonly props: TreeProps, + @inject(SketchbookTreeModel) override readonly model: SketchbookTreeModel, @inject(ContextMenuRenderer) - readonly contextMenuRenderer: ContextMenuRenderer, + override readonly contextMenuRenderer: ContextMenuRenderer, @inject(EditorManager) readonly editorManager: EditorManager ) { super(props, model, contextMenuRenderer); @@ -50,14 +50,14 @@ export class SketchbookTreeWidget extends FileTreeWidget { } @postConstruct() - protected async init(): Promise { + protected override async init(): Promise { super.init(); // cache the current open sketch uri const currentSketch = await this.sketchServiceClient.currentSketch(); this.currentSketchUri = (currentSketch && currentSketch.uri) || ''; } - protected createNodeClassNames(node: TreeNode, props: NodeProps): string[] { + protected override createNodeClassNames(node: TreeNode, props: NodeProps): string[] { const classNames = super.createNodeClassNames(node, props); if ( @@ -70,7 +70,7 @@ export class SketchbookTreeWidget extends FileTreeWidget { return classNames; } - protected renderIcon(node: TreeNode, props: NodeProps): React.ReactNode { + protected override renderIcon(node: TreeNode, props: NodeProps): React.ReactNode { if (SketchbookTree.SketchDirNode.is(node) || Sketch.isSketchFile(node.id)) { return
; } @@ -81,7 +81,7 @@ export class SketchbookTreeWidget extends FileTreeWidget { return undefined; } - protected renderTailDecorations( + protected override renderTailDecorations( node: TreeNode, props: NodeProps ): React.ReactNode { @@ -99,7 +99,7 @@ export class SketchbookTreeWidget extends FileTreeWidget { this.update(); } - protected createNodeAttributes( + protected override createNodeAttributes( node: TreeNode, props: NodeProps ): React.Attributes & React.HTMLAttributes { @@ -160,7 +160,7 @@ export class SketchbookTreeWidget extends FileTreeWidget { return undefined; } - protected handleClickEvent( + protected override handleClickEvent( node: TreeNode | undefined, event: React.MouseEvent ): void { @@ -186,7 +186,7 @@ export class SketchbookTreeWidget extends FileTreeWidget { } } - protected doToggle(event: React.MouseEvent): void { + protected override doToggle(event: React.MouseEvent): void { const nodeId = event.currentTarget.getAttribute('data-node-id'); if (nodeId) { const node = this.model.getNode(nodeId); diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree.ts index aac987f57..6726f12b6 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree.ts @@ -18,7 +18,7 @@ export class SketchbookTree extends FileNavigatorTree { @inject(ArduinoPreferences) protected readonly arduinoPreferences: ArduinoPreferences; - async resolveChildren(parent: CompositeTreeNode): Promise { + override async resolveChildren(parent: CompositeTreeNode): Promise { const showAllFiles = this.arduinoPreferences['arduino.sketchbook.showAllFiles']; diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 6c68ef55c..23a0a961e 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -95,7 +95,7 @@ export class SketchbookWidgetContribution return this.openView() as Promise; } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); registry.registerCommand(SketchbookCommands.OPEN_NEW_WINDOW, { @@ -186,7 +186,7 @@ export class SketchbookWidgetContribution }); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); // unregister main menu action diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx index ce20b43b3..f0a427de7 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget.tsx @@ -33,7 +33,7 @@ export class SketchbookWidget extends BaseWidget { this.sketchbookTreesContainer.addWidget(this.localSketchbookTreeWidget); } - protected onAfterAttach(message: Message): void { + protected override onAfterAttach(message: Message): void { super.onAfterAttach(message); Widget.attach(this.sketchbookTreesContainer, this.node); this.toDisposeOnDetach.push( @@ -45,7 +45,7 @@ export class SketchbookWidget extends BaseWidget { return this.localSketchbookTreeWidget; } - protected onActivateRequest(message: Message): void { + protected override onActivateRequest(message: Message): void { super.onActivateRequest(message); // TODO: focus the active sketchbook @@ -56,7 +56,7 @@ export class SketchbookWidget extends BaseWidget { this.node.focus(); } - protected onResize(message: Widget.ResizeMessage): void { + protected override onResize(message: Widget.ResizeMessage): void { super.onResize(message); MessageLoop.sendMessage( this.sketchbookTreesContainer, @@ -67,7 +67,7 @@ export class SketchbookWidget extends BaseWidget { } } - protected onAfterShow(msg: Message): void { + protected override onAfterShow(msg: Message): void { super.onAfterShow(msg); this.onResize(Widget.ResizeMessage.UnknownSize); } diff --git a/arduino-ide-extension/src/electron-browser/electron-window-service.ts b/arduino-ide-extension/src/electron-browser/electron-window-service.ts index 72540e680..1407ac425 100644 --- a/arduino-ide-extension/src/electron-browser/electron-window-service.ts +++ b/arduino-ide-extension/src/electron-browser/electron-window-service.ts @@ -21,7 +21,7 @@ export class ElectronWindowService extends TheiaElectronWindowService { protected readonly appStateService: FrontendApplicationStateService; @postConstruct() - protected init(): void { + protected override init(): void { this.appStateService .reachedAnyState('initialized_layout') .then(() => this.splashService.requestClose()); diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts index 84f2fe715..046ebe926 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts @@ -17,7 +17,7 @@ import { @injectable() export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { - createElectronMenuBar(): Electron.Menu { + override createElectronMenuBar(): Electron.Menu { this._toggledCommands.clear(); // https://github.com/eclipse-theia/theia/issues/8977 const menuModel = this.menuProvider.getMenu(MAIN_MENU_BAR); const template = this.fillMenuTemplate([], menuModel); @@ -29,7 +29,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { return menu; } - async setMenuBar(): Promise { + override async setMenuBar(): Promise { await this.preferencesService.ready; const createdMenuBar = this.createElectronMenuBar(); if (isOSX) { @@ -39,7 +39,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { } } - createElectronContextMenu(menuPath: MenuPath, args?: any[]): Electron.Menu { + override createElectronContextMenu(menuPath: MenuPath, args?: any[]): Electron.Menu { const menuModel = this.menuProvider.getMenu(menuPath); const template = this.fillMenuTemplate([], menuModel, args, { showDisabled: false, @@ -64,7 +64,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { return template; } - protected createOSXMenu(): Electron.MenuItemConstructorOptions { + protected override createOSXMenu(): Electron.MenuItemConstructorOptions { const { submenu } = super.createOSXMenu(); const label = 'Arduino IDE'; if (!!submenu && Array.isArray(submenu)) { @@ -96,7 +96,7 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { return { label, submenu }; } - protected handleElectronDefault( + protected override handleElectronDefault( menuNode: CompositeMenuNode, args: any[] = [], options?: ElectronMenuOptions diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts index 7e29b53b4..924051611 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts @@ -13,7 +13,7 @@ export class ElectronMenuContribution extends TheiaElectronMenuContribution implements MainMenuManager { - protected hideTopPanel(): void { + protected override hideTopPanel(): void { // NOOP // We reuse the `div` for the Arduino toolbar. } @@ -22,17 +22,17 @@ export class ElectronMenuContribution (this as any).setMenu(); } - registerCommands(registry: CommandRegistry): void { + override registerCommands(registry: CommandRegistry): void { super.registerCommands(registry); registry.unregisterCommand(ElectronCommands.CLOSE_WINDOW); } - registerMenus(registry: MenuModelRegistry): void { + override registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); registry.unregisterMenuAction(ElectronCommands.CLOSE_WINDOW); } - registerKeybindings(registry: KeybindingRegistry): void { + override registerKeybindings(registry: KeybindingRegistry): void { super.registerKeybindings(registry); registry.unregisterKeybinding(ElectronCommands.CLOSE_WINDOW.id); registry.unregisterKeybinding(ElectronCommands.ZOOM_IN.id); diff --git a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts index 360f70eed..765ac1e17 100644 --- a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts +++ b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts @@ -42,7 +42,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { @inject(SplashServiceImpl) protected readonly splashService: SplashServiceImpl; - async start(config: FrontendApplicationConfig): Promise { + override async start(config: FrontendApplicationConfig): Promise { // Explicitly set the app name to have better menu items on macOS. ("About", "Hide", and "Quit") // See: https://github.com/electron-userland/electron-builder/issues/2468 // Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701 @@ -71,7 +71,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { return typeof uri === 'string' && await fs.pathExists(uri); } - protected async launch(params: ElectronMainExecutionParams): Promise { + protected override async launch(params: ElectronMainExecutionParams): Promise { try { // When running on MacOS, we either have to wait until // 1. The `open-file` command has been received by the app, rejecting the promise @@ -143,18 +143,18 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { return electronWindow; } - protected avoidOverlap(options: TheiaBrowserWindowOptions): TheiaBrowserWindowOptions { + protected override avoidOverlap(options: TheiaBrowserWindowOptions): TheiaBrowserWindowOptions { if (this.startup) { return options; } return super.avoidOverlap(options); } - protected getTitleBarStyle(): 'native' | 'custom' { + protected override getTitleBarStyle(): 'native' | 'custom' { return 'native'; } - protected hookApplicationEvents(): void { + protected override hookApplicationEvents(): void { app.on('will-quit', this.onWillQuit.bind(this)); app.on('second-instance', this.onSecondInstance.bind(this)); app.on('window-all-closed', this.onWindowAllClosed.bind(this)); @@ -164,7 +164,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { }); } - protected async onSecondInstance(event: ElectronEvent, argv: string[], cwd: string): Promise { + protected override async onSecondInstance(event: ElectronEvent, argv: string[], cwd: string): Promise { if (!os.isOSX && await this.launchFromArgs({ cwd, argv, secondInstance: true })) { // Application has received a file in its arguments return; @@ -177,7 +177,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { * * @param options */ - async createWindow( + override async createWindow( asyncOptions: MaybePromise = this.getDefaultTheiaWindowOptions() ): Promise { let options = await asyncOptions; @@ -270,7 +270,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { this.attachClosedWorkspace(electronWindow); } - protected async startBackend(): Promise { + protected override async startBackend(): Promise { // Check if we should run everything as one process. const noBackendFork = process.argv.indexOf('--no-cluster') !== -1; // We cannot use the `process.cwd()` as the application project path (the location of the `package.json` in other words) @@ -359,7 +359,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { }); } - protected onWillQuit(event: Electron.Event): void { + protected override onWillQuit(event: Electron.Event): void { // Only add workspaces which were closed within the last second (1000 milliseconds) const threshold = Date.now() - 1000; const visited = new Set(); diff --git a/arduino-ide-extension/src/electron-main/theia/electron-main-window-service.ts b/arduino-ide-extension/src/electron-main/theia/electron-main-window-service.ts index bc5a2e91b..2248ac543 100644 --- a/arduino-ide-extension/src/electron-main/theia/electron-main-window-service.ts +++ b/arduino-ide-extension/src/electron-main/theia/electron-main-window-service.ts @@ -6,9 +6,9 @@ import { NewWindowOptions } from '@theia/core/lib/common/window'; @injectable() export class ElectronMainWindowServiceImpl extends TheiaElectronMainWindowService { @inject(ElectronMainApplication) - protected readonly app: ElectronMainApplication; + protected override readonly app: ElectronMainApplication; - openNewWindow(url: string, { external }: NewWindowOptions): undefined { + override openNewWindow(url: string, { external }: NewWindowOptions): undefined { if (!external) { const sanitizedUrl = this.sanitize(url); const existing = this.app.browserWindows.find( diff --git a/arduino-ide-extension/src/node/core-client-provider.ts b/arduino-ide-extension/src/node/core-client-provider.ts index 18b78e626..1fce98805 100644 --- a/arduino-ide-extension/src/node/core-client-provider.ts +++ b/arduino-ide-extension/src/node/core-client-provider.ts @@ -48,7 +48,7 @@ export class CoreClientProvider extends GrpcClientProvider(); } - protected async reconcileClient(): Promise { + protected override async reconcileClient(): Promise { const port = await this.daemon.getPort(); if (port && port === this._port) { @@ -64,7 +64,7 @@ export class CoreClientProvider extends GrpcClientProvider { + protected override async init(): Promise { this.daemon.ready.then(async () => { // First create the client and the instance synchronously // and notify client is ready. diff --git a/arduino-ide-extension/src/node/theia/core/backend-application.ts b/arduino-ide-extension/src/node/theia/core/backend-application.ts index 6346d5e3c..1b7d6f927 100644 --- a/arduino-ide-extension/src/node/theia/core/backend-application.ts +++ b/arduino-ide-extension/src/node/theia/core/backend-application.ts @@ -11,9 +11,9 @@ export class BackendApplication extends TheiaBackendApplication { constructor( @inject(ContributionProvider) @named(BackendApplicationContribution) - protected readonly contributionsProvider: ContributionProvider, + protected override readonly contributionsProvider: ContributionProvider, @inject(BackendApplicationCliContribution) - protected readonly cliParams: BackendApplicationCliContribution + protected override readonly cliParams: BackendApplicationCliContribution ) { super(contributionsProvider, cliParams); // Workaround for Electron not installing a handler to ignore SIGPIPE diff --git a/arduino-ide-extension/src/node/theia/env-variables/env-variables-server.ts b/arduino-ide-extension/src/node/theia/env-variables/env-variables-server.ts index 819ce028b..7380cb71e 100644 --- a/arduino-ide-extension/src/node/theia/env-variables/env-variables-server.ts +++ b/arduino-ide-extension/src/node/theia/env-variables/env-variables-server.ts @@ -7,7 +7,7 @@ import { EnvVariablesServerImpl as TheiaEnvVariablesServerImpl } from '@theia/co @injectable() export class EnvVariablesServer extends TheiaEnvVariablesServerImpl { - protected readonly configDirUri = Promise.resolve( + protected override readonly configDirUri = Promise.resolve( FileUri.create( join(homedir(), BackendApplicationConfigProvider.get().configDirName) ).toString() diff --git a/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts b/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts index fd322ca4c..de25e7e89 100644 --- a/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts +++ b/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts @@ -11,7 +11,7 @@ export class DefaultWorkspaceServer extends TheiaDefaultWorkspaceServer { @inject(ILogger) protected readonly logger: ILogger; - protected async getWorkspaceURIFromCli(): Promise { + protected override async getWorkspaceURIFromCli(): Promise { try { const config = await this.configService.getConfiguration(); return config.sketchDirUri; diff --git a/arduino-ide-extension/src/test/node/arduino-daemon-impl.test.ts b/arduino-ide-extension/src/test/node/arduino-daemon-impl.test.ts index 0fd6cf4d9..b0f44b701 100644 --- a/arduino-ide-extension/src/test/node/arduino-daemon-impl.test.ts +++ b/arduino-ide-extension/src/test/node/arduino-daemon-impl.test.ts @@ -16,15 +16,15 @@ class SilentArduinoDaemonImpl extends ArduinoDaemonImpl { super(); } - onData(data: string): void { + override onData(data: string): void { // NOOP } - async spawnDaemonProcess(): Promise<{ daemon: ChildProcess; port: string }> { + override async spawnDaemonProcess(): Promise<{ daemon: ChildProcess; port: string }> { return super.spawnDaemonProcess(); } - protected async getSpawnArgs(): Promise { + protected override async getSpawnArgs(): Promise { const cliConfigPath = await this.initCliConfig(); return [ 'daemon', diff --git a/arduino-ide-extension/tsconfig.json b/arduino-ide-extension/tsconfig.json index e35c848fa..24604fe4c 100644 --- a/arduino-ide-extension/tsconfig.json +++ b/arduino-ide-extension/tsconfig.json @@ -6,6 +6,7 @@ "noEmitOnError": true, "noImplicitThis": true, "noUnusedLocals": true, + "noImplicitOverride": true, "strictNullChecks": true, "experimentalDecorators": true, "downlevelIteration": true, From 307546ce618a96a54d07273e979fa2e7d625e3bf Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 20 May 2022 15:15:48 +0200 Subject: [PATCH 05/45] Switched to sketchRef for examples and builtins. Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 1 + .../src/browser/contributions/examples.ts | 6 +- .../protocol/sketches-service-client-impl.ts | 14 +- .../src/common/protocol/sketches-service.ts | 10 +- .../src/node/examples-service-impl.ts | 122 +++++++++++++++++- .../src/node/sketches-service-impl.ts | 2 +- yarn.lock | 12 ++ 7 files changed, 149 insertions(+), 18 deletions(-) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 3e6c4c0a6..9573b39f4 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -64,6 +64,7 @@ "btoa": "^1.2.1", "dateformat": "^3.0.3", "deepmerge": "2.0.1", + "deep-equals": "^0.0.2", "electron-updater": "^4.6.5", "fast-safe-stringify": "^2.1.1", "glob": "^7.1.6", diff --git a/arduino-ide-extension/src/browser/contributions/examples.ts b/arduino-ide-extension/src/browser/contributions/examples.ts index 8b4a61a70..8ce379e4d 100644 --- a/arduino-ide-extension/src/browser/contributions/examples.ts +++ b/arduino-ide-extension/src/browser/contributions/examples.ts @@ -21,7 +21,7 @@ import { MenuModelRegistry, } from './contribution'; import { NotificationCenter } from '../notification-center'; -import { Board, Sketch, SketchContainer } from '../../common/protocol'; +import { Board, SketchRef, SketchContainer } from '../../common/protocol'; import { nls } from '@theia/core/lib/common'; @injectable() @@ -82,7 +82,7 @@ export abstract class Examples extends SketchContribution { registerRecursively( sketchContainerOrPlaceholder: | SketchContainer - | (Sketch | SketchContainer)[] + | (SketchRef | SketchContainer)[] | string, menuPath: MenuPath, pushToDispose: DisposableCollection = new DisposableCollection(), @@ -100,7 +100,7 @@ export abstract class Examples extends SketchContribution { ) ); } else { - const sketches: Sketch[] = []; + const sketches: SketchRef[] = []; const children: SketchContainer[] = []; let submenuPath = menuPath; diff --git a/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts b/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts index 970032a1c..72d543de3 100644 --- a/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts +++ b/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts @@ -10,7 +10,7 @@ import { DisposableCollection } from '@theia/core/lib/common/disposable'; import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application'; import { Sketch, SketchesService } from '../../common/protocol'; import { ConfigService } from './config-service'; -import { SketchContainer } from './sketches-service'; +import { SketchContainer, SketchRef } from './sketches-service'; import { ARDUINO_CLOUD_FOLDER, REMOTE_SKETCHBOOK_FOLDER, @@ -40,10 +40,10 @@ export class SketchesServiceClientImpl protected readonly configService: ConfigService; protected toDispose = new DisposableCollection(); - protected sketches = new Map(); + protected sketches = new Map(); protected sketchbookDidChangeEmitter = new Emitter<{ - created: Sketch[]; - removed: Sketch[]; + created: SketchRef[]; + removed: SketchRef[]; }>(); readonly onSketchbookDidChange = this.sketchbookDidChangeEmitter.event; @@ -145,10 +145,10 @@ export class SketchesServiceClientImpl private fireSoonHandle?: number; private bufferedSketchbookEvents: { type: 'created' | 'removed'; - sketch: Sketch; + sketch: SketchRef; }[] = []; - private fireSoon(sketch: Sketch, type: 'created' | 'removed'): void { + private fireSoon(sketch: SketchRef, type: 'created' | 'removed'): void { this.bufferedSketchbookEvents.push({ type, sketch }); if (typeof this.fireSoonHandle === 'number') { @@ -156,7 +156,7 @@ export class SketchesServiceClientImpl } this.fireSoonHandle = window.setTimeout(() => { - const event: { created: Sketch[]; removed: Sketch[] } = { + const event: { created: SketchRef[]; removed: SketchRef[] } = { created: [], removed: [], }; diff --git a/arduino-ide-extension/src/common/protocol/sketches-service.ts b/arduino-ide-extension/src/common/protocol/sketches-service.ts index 06f979910..17da70ac4 100644 --- a/arduino-ide-extension/src/common/protocol/sketches-service.ts +++ b/arduino-ide-extension/src/common/protocol/sketches-service.ts @@ -81,9 +81,11 @@ export interface SketchesService { getIdeTempFolderUri(sketch: Sketch): Promise; } -export interface Sketch { +export interface SketchRef { readonly name: string; readonly uri: string; // `LocationPath` +} +export interface Sketch extends SketchRef { readonly mainFileUri: string; // `MainFile` readonly otherSketchFileUris: string[]; // `OtherSketchFiles` readonly additionalFileUris: string[]; // `AdditionalFiles` @@ -134,7 +136,7 @@ export namespace Sketch { export interface SketchContainer { readonly label: string; readonly children: SketchContainer[]; - readonly sketches: Sketch[]; + readonly sketches: SketchRef[]; } export namespace SketchContainer { export function is(arg: any): arg is SketchContainer { @@ -174,8 +176,8 @@ export namespace SketchContainer { return container; } - export function toArray(container: SketchContainer): Sketch[] { - const visit = (parent: SketchContainer, toPushSketch: Sketch[]) => { + export function toArray(container: SketchContainer): SketchRef[] { + const visit = (parent: SketchContainer, toPushSketch: SketchRef[]) => { toPushSketch.push(...parent.sketches); parent.children.map((child) => visit(child, toPushSketch)); }; diff --git a/arduino-ide-extension/src/node/examples-service-impl.ts b/arduino-ide-extension/src/node/examples-service-impl.ts index b3730ce53..eb51a7724 100644 --- a/arduino-ide-extension/src/node/examples-service-impl.ts +++ b/arduino-ide-extension/src/node/examples-service-impl.ts @@ -1,4 +1,8 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import { join, basename } from 'path'; import * as fs from 'fs'; import { promisify } from 'util'; @@ -13,6 +17,8 @@ import { LibraryService, } from '../common/protocol'; import { ConfigServiceImpl } from './config-service-impl'; +import { duration } from '../common/decorators'; +const eq = require('deep-equals'); @injectable() export class ExamplesServiceImpl implements ExamplesService { @@ -51,6 +57,116 @@ export class ExamplesServiceImpl implements ExamplesService { user: SketchContainer[]; current: SketchContainer[]; any: SketchContainer[]; + }> { + const [old, _new] = await Promise.all([ + this.installedOld({ fqbn }), + this.installedNew({ fqbn }), + ]); + // Compare new and old + if (eq(old, _new)) { + console.log('---- happiness. the packages are the same'); + } else { + console.error('---- yayy :( the packages are not the same'); + } + + return old; + } + + @duration() + async installedOld({ fqbn }: { fqbn?: string }): Promise<{ + user: SketchContainer[]; + current: SketchContainer[]; + any: SketchContainer[]; + }> { + const user: SketchContainer[] = []; + const current: SketchContainer[] = []; + const any: SketchContainer[] = []; + const packages: LibraryPackage[] = await this.libraryService.list({ + fqbn, + }); + for (const pkg of packages) { + const container = await this.tryGroupExamplesOld(pkg); + const { location } = pkg; + if (location === LibraryLocation.USER) { + user.push(container); + } else if ( + location === LibraryLocation.PLATFORM_BUILTIN || + LibraryLocation.REFERENCED_PLATFORM_BUILTIN + ) { + current.push(container); + } else { + any.push(container); + } + } + return { user, current, any }; + } + + /** + * The CLI provides direct FS paths to the examples so that menus and menu groups cannot be built for the UI by traversing the + * folder hierarchy. This method tries to workaround it by falling back to the `installDirUri` and manually creating the + * location of the examples. Otherwise it creates the example container from the direct examples FS paths. + */ + protected async tryGroupExamplesOld({ + label, + exampleUris, + installDirUri, + }: LibraryPackage): Promise { + const paths = exampleUris.map((uri) => FileUri.fsPath(uri)); + if (installDirUri) { + for (const example of [ + 'example', + 'Example', + 'EXAMPLE', + 'examples', + 'Examples', + 'EXAMPLES', + ]) { + const examplesPath = join(FileUri.fsPath(installDirUri), example); + const exists = await promisify(fs.exists)(examplesPath); + const isDir = + exists && (await promisify(fs.lstat)(examplesPath)).isDirectory(); + if (isDir) { + const fileNames = await promisify(fs.readdir)(examplesPath); + const children: SketchContainer[] = []; + const sketches: Sketch[] = []; + for (const fileName of fileNames) { + const subPath = join(examplesPath, fileName); + const subIsDir = (await promisify(fs.lstat)(subPath)).isDirectory(); + if (subIsDir) { + const sketch = await this.tryLoadSketch(subPath); + if (!sketch) { + const container = await this.load(subPath); + if (container.children.length || container.sketches.length) { + children.push(container); + } + } else { + sketches.push(sketch); + } + } + } + return { + label, + children, + sketches, + }; + } + } + } + const sketches = await Promise.all( + paths.map((path) => this.tryLoadSketch(path)) + ); + return { + label, + children: [], + sketches: sketches.filter(notEmpty), + }; + } + + @duration() + async installedNew({ fqbn }: { fqbn?: string }): Promise<{ + user: SketchContainer[]; + current: SketchContainer[]; + any: SketchContainer[]; }> { const user: SketchContainer[] = []; const current: SketchContainer[] = []; @@ -59,7 +175,7 @@ export class ExamplesServiceImpl implements ExamplesService { fqbn, }); for (const pkg of packages) { - const container = await this.tryGroupExamples(pkg); + const container = await this.tryGroupExamplesNew(pkg); const { location } = pkg; if (location === LibraryLocation.USER) { user.push(container); @@ -80,7 +196,7 @@ export class ExamplesServiceImpl implements ExamplesService { * folder hierarchy. This method tries to workaround it by falling back to the `installDirUri` and manually creating the * location of the examples. Otherwise it creates the example container from the direct examples FS paths. */ - protected async tryGroupExamples({ + protected async tryGroupExamplesNew({ label, exampleUris, installDirUri, diff --git a/arduino-ide-extension/src/node/sketches-service-impl.ts b/arduino-ide-extension/src/node/sketches-service-impl.ts index b197f2125..f35fdce45 100644 --- a/arduino-ide-extension/src/node/sketches-service-impl.ts +++ b/arduino-ide-extension/src/node/sketches-service-impl.ts @@ -523,7 +523,7 @@ interface SketchContainerWithDetails extends SketchContainer { * from other new sketches I created today. * If 'sketch_jul8a' is already used, go with 'sketch_jul8b'. * If 'sketch_jul8b' already used, go with 'sketch_jul8c'. - * When it reacheas 'sketch_jul8z', go with 'sketch_jul8aa', + * When it reach 'sketch_jul8z', go with 'sketch_jul8aa', * and so on. */ function sketchIndexToLetters(num: number): string { diff --git a/yarn.lock b/yarn.lock index 212d2689c..8009ba991 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6139,6 +6139,13 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" +deep-equals@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/deep-equals/-/deep-equals-0.0.2.tgz#21c164c55d1a50802d15d94f801d32585a99f0ce" + integrity sha1-IcFkxV0aUIAtFdlPgB0yWFqZ8M4= + dependencies: + ramda "^0.23.0" + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -12350,6 +12357,11 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +ramda@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.23.0.tgz#ccd13fff73497a93974e3e86327bfd87bd6e8e2b" + integrity sha1-zNE//3NJepOXTj6GMnv9h71ujis= + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" From 77d74166e86d162a4d005f3f8d417c9b0bbb8f65 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Sat, 21 May 2022 15:34:16 +0200 Subject: [PATCH 06/45] can disable splash. Signed-off-by: Akos Kitta --- .vscode/launch.json | 3 ++- .../electron-main/theia/electron-main-application.ts | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d6ed25954..aa726a434 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,7 +20,8 @@ "--remote-debugging-port=9222", "--no-app-auto-install", "--plugins=local-dir:../plugins", - "--hosted-plugin-inspect=9339" + "--hosted-plugin-inspect=9339", + "--nosplash" ], "env": { "NODE_ENV": "development" diff --git a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts index 765ac1e17..67a6212c4 100644 --- a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts +++ b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts @@ -34,6 +34,14 @@ interface WorkspaceOptions { const WORKSPACES = 'workspaces'; +/** + * Purely a dev thing. If you start the app with the `--nosplash` argument, + * then you won't have the splash screen (which is always on top :confused:) and can debug the app at startup. + * Note: if you start the app from VS Code with the `App (Electron)` config, the splash screen will be disabled. + */ +const APP_STARTED_WITH_NOSPLASH = + typeof process !== 'undefined' && process.argv.indexOf('--nosplash') !== -1; + @injectable() export class ElectronMainApplication extends TheiaElectronMainApplication { protected startup = false; @@ -183,7 +191,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { let options = await asyncOptions; options = this.avoidOverlap(options); let electronWindow: BrowserWindow | undefined; - if (this.windows.size) { + if (this.windows.size || APP_STARTED_WITH_NOSPLASH) { electronWindow = await this.doCreateWindow(options); } else { const { bounds } = screen.getDisplayNearestPoint( From 99caaa8f7f653dfc0dad4bdba90eb5af3a2e082d Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Sat, 21 May 2022 15:38:29 +0200 Subject: [PATCH 07/45] speed up examples load. Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 2 + .../src/common/protocol/sketches-service.ts | 16 ++ .../src/node/examples-service-impl.ts | 173 ++++++++++++------ yarn.lock | 14 +- 4 files changed, 150 insertions(+), 55 deletions(-) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 9573b39f4..ae8a6d9d6 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -65,6 +65,8 @@ "dateformat": "^3.0.3", "deepmerge": "2.0.1", "deep-equals": "^0.0.2", + "deep-object-diff": "^1.1.7", + "deep-sort-object": "^1.0.2", "electron-updater": "^4.6.5", "fast-safe-stringify": "^2.1.1", "glob": "^7.1.6", diff --git a/arduino-ide-extension/src/common/protocol/sketches-service.ts b/arduino-ide-extension/src/common/protocol/sketches-service.ts index 17da70ac4..3b85af8cc 100644 --- a/arduino-ide-extension/src/common/protocol/sketches-service.ts +++ b/arduino-ide-extension/src/common/protocol/sketches-service.ts @@ -85,6 +85,15 @@ export interface SketchRef { readonly name: string; readonly uri: string; // `LocationPath` } +export namespace SketchRef { + export function fromUri(uriLike: string | URI): SketchRef { + const uri = typeof uriLike === 'string' ? new URI(uriLike) : uriLike; + return { + name: uri.path.base, + uri: typeof uriLike === 'string' ? uriLike : uriLike.toString(), + }; + } +} export interface Sketch extends SketchRef { readonly mainFileUri: string; // `MainFile` readonly otherSketchFileUris: string[]; // `OtherSketchFiles` @@ -139,6 +148,13 @@ export interface SketchContainer { readonly sketches: SketchRef[]; } export namespace SketchContainer { + export function create(label: string): SketchContainer { + return { + label, + children: [], + sketches: [], + }; + } export function is(arg: any): arg is SketchContainer { return ( !!arg && diff --git a/arduino-ide-extension/src/node/examples-service-impl.ts b/arduino-ide-extension/src/node/examples-service-impl.ts index eb51a7724..d7cbf3bd9 100644 --- a/arduino-ide-extension/src/node/examples-service-impl.ts +++ b/arduino-ide-extension/src/node/examples-service-impl.ts @@ -8,7 +8,11 @@ import * as fs from 'fs'; import { promisify } from 'util'; import { FileUri } from '@theia/core/lib/node/file-uri'; import { notEmpty } from '@theia/core/lib/common/objects'; -import { Sketch, SketchContainer } from '../common/protocol/sketches-service'; +import { + Sketch, + SketchRef, + SketchContainer, +} from '../common/protocol/sketches-service'; import { SketchesServiceImpl } from './sketches-service-impl'; import { ExamplesService } from '../common/protocol/examples-service'; import { @@ -18,7 +22,11 @@ import { } from '../common/protocol'; import { ConfigServiceImpl } from './config-service-impl'; import { duration } from '../common/decorators'; +import { URI } from '@theia/core/lib/common/uri'; +import { Path } from '@theia/core/lib/common/path'; const eq = require('deep-equals'); +import { diff } from 'deep-object-diff'; +const deepSort = require('deep-sort-object'); @injectable() export class ExamplesServiceImpl implements ExamplesService { @@ -67,6 +75,8 @@ export class ExamplesServiceImpl implements ExamplesService { console.log('---- happiness. the packages are the same'); } else { console.error('---- yayy :( the packages are not the same'); + const diffObj = diff(old, _new); + console.error(JSON.stringify(diffObj)); } return old; @@ -98,7 +108,10 @@ export class ExamplesServiceImpl implements ExamplesService { any.push(container); } } - return { user, current, any }; + user.sort((left, right) => left.label.localeCompare(right.label)); + current.sort((left, right) => left.label.localeCompare(right.label)); + any.sort((left, right) => left.label.localeCompare(right.label)); + return deepSort({ user, current, any }); } /** @@ -128,7 +141,7 @@ export class ExamplesServiceImpl implements ExamplesService { if (isDir) { const fileNames = await promisify(fs.readdir)(examplesPath); const children: SketchContainer[] = []; - const sketches: Sketch[] = []; + const sketches: SketchRef[] = []; for (const fileName of fileNames) { const subPath = join(examplesPath, fileName); const subIsDir = (await promisify(fs.lstat)(subPath)).isDirectory(); @@ -138,9 +151,15 @@ export class ExamplesServiceImpl implements ExamplesService { const container = await this.load(subPath); if (container.children.length || container.sketches.length) { children.push(container); + children.sort((left, right) => + left.label.localeCompare(right.label) + ); } } else { - sketches.push(sketch); + sketches.push({ name: sketch.name, uri: sketch.uri }); + sketches.sort((left, right) => + left.name.localeCompare(right.name) + ); } } } @@ -188,7 +207,10 @@ export class ExamplesServiceImpl implements ExamplesService { any.push(container); } } - return { user, current, any }; + user.sort((left, right) => left.label.localeCompare(right.label)); + current.sort((left, right) => left.label.localeCompare(right.label)); + any.sort((left, right) => left.label.localeCompare(right.label)); + return deepSort({ user, current, any }); } /** @@ -201,55 +223,96 @@ export class ExamplesServiceImpl implements ExamplesService { exampleUris, installDirUri, }: LibraryPackage): Promise { - const paths = exampleUris.map((uri) => FileUri.fsPath(uri)); - if (installDirUri) { - for (const example of [ - 'example', - 'Example', - 'EXAMPLE', - 'examples', - 'Examples', - 'EXAMPLES', - ]) { - const examplesPath = join(FileUri.fsPath(installDirUri), example); - const exists = await promisify(fs.exists)(examplesPath); - const isDir = - exists && (await promisify(fs.lstat)(examplesPath)).isDirectory(); - if (isDir) { - const fileNames = await promisify(fs.readdir)(examplesPath); - const children: SketchContainer[] = []; - const sketches: Sketch[] = []; - for (const fileName of fileNames) { - const subPath = join(examplesPath, fileName); - const subIsDir = (await promisify(fs.lstat)(subPath)).isDirectory(); - if (subIsDir) { - const sketch = await this.tryLoadSketch(subPath); - if (!sketch) { - const container = await this.load(subPath); - if (container.children.length || container.sketches.length) { - children.push(container); - } - } else { - sketches.push(sketch); - } - } - } - return { - label, - children, - sketches, - }; - } + const container = SketchContainer.create(label); + if (!installDirUri || !exampleUris.length) { + return container; + } + // Args example: + // exampleUris + // 0:'file:///Users/a.kitta/Documents/Arduino/libraries/ATOM_DTU_CAT1/examples/MQTT' + // 1:'file:///Users/a.kitta/Documents/Arduino/libraries/ATOM_DTU_CAT1/examples/Modbus/ModBus-RTU/Master' + // 2:'file:///Users/a.kitta/Documents/Arduino/libraries/ATOM_DTU_CAT1/examples/Modbus/ModBus-RTU/Slave' + // installDirUri + // 'file:///Users/a.kitta/Documents/Arduino/libraries/ATOM_DTU_CAT1' + // Expected menu structure: + // ATOM_DTU_CAT1 > Modbus > ModBus-RTU > Master + // | > Slave + // > MQTT + const logInfo = (ref: SketchRef) => + `Example URI: ${ref.uri}, install location URI: ${installDirUri}.`; + for (const ref of exampleUris.map(SketchRef.fromUri)) { + const path = new URI(installDirUri).relative(new URI(ref.uri)); + if (!path) { + console.warn( + `Could not resolve the sketch location from its install location. Skipping. ${logInfo( + ref + )}` + ); + continue; + } + if (path.isAbsolute) { + console.warn( + `Expected a relative path between the sketch and the install locations. Skipping. Path was: ${path}. ${logInfo( + ref + )}` + ); + continue; + } + const pathSegments = path.toString().split(Path.separator); + if (pathSegments.length < 2) { + console.warn( + `Expected at least two segments long relative path. Skipping. Path segments were: ${pathSegments}. ${logInfo( + ref + )}` + ); + continue; + } + // the relative must start start with `example` or `Examples` or `EXAMPLE`, .etc. It's open source. + if (!/^examples?$/gi.test(pathSegments[0])) { + console.warn( + `First segment must start with "examples-like". More formally: \`/^examples?$/gi\`. Path segments were: ${pathSegments}. ${logInfo( + ref + )}` + ); } + const getOrCreateChildContainer = ( + label: string, + parent: SketchContainer + ) => { + let child = parent.children.find( + ({ label: childLabel }) => childLabel === label + ); + if (!child) { + child = SketchContainer.create(label); + parent.children.push(child); + //TODO: remove or move sort + parent.children.sort((left, right) => + left.label.localeCompare(right.label) + ); + } + return child; + }; + const refContainer = pathSegments.reduce( + (container, segment, index, segments) => { + if (index === 0) { + // skip the first "example-like" segment + return container; + } + if (index === segments.length - 1) { + // if last segment, it's the example sketch itself, do not create container for it. + return container; + } + return getOrCreateChildContainer(segment, container); + }, + container + ); + refContainer.sketches.push(ref); + //TODO: remove or move sort + refContainer.sketches.sort((left, right) => + left.name.localeCompare(right.name) + ); } - const sketches = await Promise.all( - paths.map((path) => this.tryLoadSketch(path)) - ); - return { - label, - children: [], - sketches: sketches.filter(notEmpty), - }; + return container; } // Built-ins are included inside the IDE. @@ -262,17 +325,19 @@ export class ExamplesServiceImpl implements ExamplesService { throw new Error(`${path} is not a directory.`); } const names = await promisify(fs.readdir)(path); - const sketches: Sketch[] = []; + const sketches: SketchRef[] = []; const children: SketchContainer[] = []; for (const p of names.map((name) => join(path, name))) { const stat = await promisify(fs.stat)(p); if (stat.isDirectory()) { const sketch = await this.tryLoadSketch(p); if (sketch) { - sketches.push(sketch); + sketches.push({ name: sketch.name, uri: sketch.uri }); + sketches.sort((left, right) => left.name.localeCompare(right.name)); } else { const child = await this.load(p); children.push(child); + children.sort((left, right) => left.label.localeCompare(right.label)); } } } diff --git a/yarn.lock b/yarn.lock index 8009ba991..c22165fb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6156,6 +6156,18 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deep-object-diff@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.7.tgz#348b3246f426427dd633eaa50e1ed1fc2eafc7e4" + integrity sha512-QkgBca0mL08P6HiOjoqvmm6xOAl2W6CT2+34Ljhg0OeFan8cwlcdq8jrLKsBBuUFAZLsN5b6y491KdKEoSo9lg== + +deep-sort-object@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/deep-sort-object/-/deep-sort-object-1.0.2.tgz#3892dcef5dfd0efc2d6fa96beabccb33cd8ef91f" + integrity sha1-OJLc7139Dvwtb6lr6rzLM82O+R8= + dependencies: + is-plain-object "^2.0.1" + deepmerge@*, deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" @@ -8996,7 +9008,7 @@ is-plain-obj@^4.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.0.0.tgz#06c0999fd7574edf5a906ba5644ad0feb3a84d22" integrity sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw== -is-plain-object@^2.0.3, is-plain-object@^2.0.4: +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== From 930112189205c6c5a6d880441acaca752170f3cc Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Sat, 21 May 2022 16:08:34 +0200 Subject: [PATCH 08/45] disabled old way of computing the examples. Signed-off-by: Akos Kitta --- .../src/node/examples-service-impl.ts | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/arduino-ide-extension/src/node/examples-service-impl.ts b/arduino-ide-extension/src/node/examples-service-impl.ts index d7cbf3bd9..305f5e317 100644 --- a/arduino-ide-extension/src/node/examples-service-impl.ts +++ b/arduino-ide-extension/src/node/examples-service-impl.ts @@ -24,9 +24,6 @@ import { ConfigServiceImpl } from './config-service-impl'; import { duration } from '../common/decorators'; import { URI } from '@theia/core/lib/common/uri'; import { Path } from '@theia/core/lib/common/path'; -const eq = require('deep-equals'); -import { diff } from 'deep-object-diff'; -const deepSort = require('deep-sort-object'); @injectable() export class ExamplesServiceImpl implements ExamplesService { @@ -66,20 +63,20 @@ export class ExamplesServiceImpl implements ExamplesService { current: SketchContainer[]; any: SketchContainer[]; }> { - const [old, _new] = await Promise.all([ - this.installedOld({ fqbn }), + const [/*old,*/ _new] = await Promise.all([ + // this.installedOld({ fqbn }), this.installedNew({ fqbn }), ]); // Compare new and old - if (eq(old, _new)) { - console.log('---- happiness. the packages are the same'); - } else { - console.error('---- yayy :( the packages are not the same'); - const diffObj = diff(old, _new); - console.error(JSON.stringify(diffObj)); - } + // if (eq(old, _new)) { + // console.log('---- happiness. the packages are the same'); + // } else { + // console.error('---- yayy :( the packages are not the same'); + // const diffObj = diff(old, _new); + // console.error(JSON.stringify(diffObj)); + // } - return old; + return _new; } @duration() @@ -108,10 +105,10 @@ export class ExamplesServiceImpl implements ExamplesService { any.push(container); } } - user.sort((left, right) => left.label.localeCompare(right.label)); - current.sort((left, right) => left.label.localeCompare(right.label)); - any.sort((left, right) => left.label.localeCompare(right.label)); - return deepSort({ user, current, any }); + // user.sort((left, right) => left.label.localeCompare(right.label)); + // current.sort((left, right) => left.label.localeCompare(right.label)); + // any.sort((left, right) => left.label.localeCompare(right.label)); + return { user, current, any }; } /** @@ -207,10 +204,10 @@ export class ExamplesServiceImpl implements ExamplesService { any.push(container); } } - user.sort((left, right) => left.label.localeCompare(right.label)); - current.sort((left, right) => left.label.localeCompare(right.label)); - any.sort((left, right) => left.label.localeCompare(right.label)); - return deepSort({ user, current, any }); + // user.sort((left, right) => left.label.localeCompare(right.label)); + // current.sort((left, right) => left.label.localeCompare(right.label)); + // any.sort((left, right) => left.label.localeCompare(right.label)); + return { user, current, any }; } /** From 23a16938a9f38870e059c3413b5a162aa76df924 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Sat, 21 May 2022 16:14:15 +0200 Subject: [PATCH 09/45] do not resolve all sketches as possible ws roots. Signed-off-by: Akos Kitta --- .../theia/workspace/workspace-service.ts | 115 +++++++++--------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 02f8213cc..86c998ea1 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -14,13 +14,9 @@ import { ConfigService } from '../../../common/protocol/config-service'; import { SketchesService, Sketch, - SketchContainer, } from '../../../common/protocol/sketches-service'; -import { ArduinoWorkspaceRootResolver } from '../../arduino-workspace-resolver'; import { BoardsServiceProvider } from '../../boards/boards-service-provider'; import { BoardsConfig } from '../../boards/boards-config'; -import { nls } from '@theia/core/lib/common'; -import { URI as VSCodeUri } from '@theia/core/shared/vscode-uri'; @injectable() export class WorkspaceService extends TheiaWorkspaceService { @@ -45,12 +41,9 @@ export class WorkspaceService extends TheiaWorkspaceService { @inject(BoardsServiceProvider) protected readonly boardsServiceProvider: BoardsServiceProvider; - private application: FrontendApplication; - private workspaceUri?: Promise; private version?: string; async onStart(application: FrontendApplication): Promise { - this.application = application; const info = await this.applicationServer.getApplicationInfo(); this.version = info?.version; application.shell.onDidChangeCurrentWidget( @@ -64,7 +57,9 @@ export class WorkspaceService extends TheiaWorkspaceService { // Was copied from the Theia implementation. // Unlike the default behavior, IDE2 does not check the existence of the workspace before open. - protected override async doGetDefaultWorkspaceUri(): Promise { + protected override async doGetDefaultWorkspaceUri(): Promise< + string | undefined + > { // If an empty window is explicitly requested do not restore a previous workspace. // Note: `window.location.hash` includes leading "#" if non-empty. if (window.location.hash === `#${DEFAULT_WINDOW_HASH}`) { @@ -86,51 +81,51 @@ export class WorkspaceService extends TheiaWorkspaceService { } } - protected override getDefaultWorkspaceUri(): Promise { - if (this.workspaceUri) { - // Avoid creating a new sketch twice - return this.workspaceUri; - } - this.workspaceUri = (async () => { - try { - const hash = window.location.hash; - const [recentWorkspacesPaths, recentSketches] = await Promise.all([ - this.server.getRecentWorkspaces(), - this.sketchService - .getSketches({}) - .then((container) => - SketchContainer.toArray(container).map((s) => s.uri) - ), - ]); - // On Dindows, `getRecentWorkspaces` returns only file paths, not URIs as expected by the `isValid` method. - const recentWorkspaces = recentWorkspacesPaths.map((e) => - VSCodeUri.file(e).toString() - ); - const toOpen = await new ArduinoWorkspaceRootResolver({ - isValid: this.isValid.bind(this), - }).resolve({ hash, recentWorkspaces, recentSketches }); - if (toOpen) { - const { uri } = toOpen; - await this.server.setMostRecentlyUsedWorkspace(uri); - return toOpen.uri; - } - return (await this.sketchService.createNewSketch()).uri; - } catch (err) { - this.appStateService - .reachedState('ready') - .then(() => this.application.shell.update()); - this.logger.fatal(`Failed to determine the sketch directory: ${err}`); - this.messageService.error( - nls.localize( - 'theia/workspace/sketchDirectoryError', - 'There was an error creating the sketch directory. See the log for more details. The application will probably not work as expected.' - ) - ); - return super.getDefaultWorkspaceUri(); - } - })(); - return this.workspaceUri; - } + // protected override getDefaultWorkspaceUri(): Promise { + // if (this.workspaceUri) { + // // Avoid creating a new sketch twice + // return this.workspaceUri; + // } + // this.workspaceUri = (async () => { + // try { + // const hash = window.location.hash; + // const [recentWorkspacesPaths, recentSketches] = await Promise.all([ + // this.server.getRecentWorkspaces(), + // this.sketchService + // .getSketches({}) + // .then((container) => + // SketchContainer.toArray(container).map((s) => s.uri) + // ), + // ]); + // // On Dindows, `getRecentWorkspaces` returns only file paths, not URIs as expected by the `isValid` method. + // const recentWorkspaces = recentWorkspacesPaths.map((e) => + // VSCodeUri.file(e).toString() + // ); + // const toOpen = await new ArduinoWorkspaceRootResolver({ + // isValid: this.isValid.bind(this), + // }).resolve({ hash, recentWorkspaces, recentSketches }); + // if (toOpen) { + // const { uri } = toOpen; + // await this.server.setMostRecentlyUsedWorkspace(uri); + // return toOpen.uri; + // } + // return (await this.sketchService.createNewSketch()).uri; + // } catch (err) { + // this.appStateService + // .reachedState('ready') + // .then(() => this.application.shell.update()); + // this.logger.fatal(`Failed to determine the sketch directory: ${err}`); + // this.messageService.error( + // nls.localize( + // 'theia/workspace/sketchDirectoryError', + // 'There was an error creating the sketch directory. See the log for more details. The application will probably not work as expected.' + // ) + // ); + // return super.getDefaultWorkspaceUri(); + // } + // })(); + // return this.workspaceUri; + // } protected override openNewWindow(workspacePath: string): void { const { boardsConfig } = this.boardsServiceProvider; @@ -142,13 +137,13 @@ export class WorkspaceService extends TheiaWorkspaceService { this.windowService.openNewWindow(url.toString()); } - private async isValid(uri: string): Promise { - const exists = await this.fileService.exists(new URI(uri)); - if (!exists) { - return false; - } - return this.sketchService.isSketchFolder(uri); - } + // private async isValid(uri: string): Promise { + // const exists = await this.fileService.exists(new URI(uri)); + // if (!exists) { + // return false; + // } + // return this.sketchService.isSketchFolder(uri); + // } protected onCurrentWidgetChange({ newValue, From ba1ff1a0d488b73aba67144dc35df756f88a709d Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Sat, 21 May 2022 17:27:57 +0200 Subject: [PATCH 10/45] Generate bultin examples structure at build time. Signed-off-by: Akos Kitta --- .../scripts/download-examples.js | 105 ++++++++++++++---- .../src/node/examples-service-impl.ts | 50 ++++++++- 2 files changed, 128 insertions(+), 27 deletions(-) diff --git a/arduino-ide-extension/scripts/download-examples.js b/arduino-ide-extension/scripts/download-examples.js index a393c5552..c7bcf9865 100644 --- a/arduino-ide-extension/scripts/download-examples.js +++ b/arduino-ide-extension/scripts/download-examples.js @@ -4,30 +4,93 @@ const version = '1.9.1'; (async () => { + const os = require('os'); + const { promises: fs } = require('fs'); + const path = require('path'); + const shell = require('shelljs'); + const { v4 } = require('uuid'); - const os = require('os'); - const path = require('path'); - const shell = require('shelljs'); - const { v4 } = require('uuid'); + const repository = path.join(os.tmpdir(), `${v4()}-arduino-examples`); + if (shell.mkdir('-p', repository).code !== 0) { + shell.exit(1); + } - const repository = path.join(os.tmpdir(), `${v4()}-arduino-examples`); - if (shell.mkdir('-p', repository).code !== 0) { - shell.exit(1); - process.exit(1); - } - - if (shell.exec(`git clone https://github.com/arduino/arduino-examples.git ${repository}`).code !== 0) { - shell.exit(1); - process.exit(1); - } + if ( + shell.exec( + `git clone https://github.com/arduino/arduino-examples.git ${repository}` + ).code !== 0 + ) { + shell.exit(1); + } - if (shell.exec(`git -C ${repository} checkout tags/${version} -b ${version}`).code !== 0) { - shell.exit(1); - process.exit(1); - } + if ( + shell.exec(`git -C ${repository} checkout tags/${version} -b ${version}`) + .code !== 0 + ) { + shell.exit(1); + } - const destination = path.join(__dirname, '..', 'Examples'); - shell.mkdir('-p', destination); - shell.cp('-fR', path.join(repository, 'examples', '*'), destination); + const destination = path.join(__dirname, '..', 'Examples'); + shell.mkdir('-p', destination); + shell.cp('-fR', path.join(repository, 'examples', '*'), destination); + const isSketch = async (pathLike) => { + try { + const names = await fs.readdir(pathLike); + const dirName = path.basename(pathLike); + return names.indexOf(`${dirName}.ino`) !== -1; + } catch (e) { + if (e.code === 'ENOTDIR') { + return false; + } + throw e; + } + }; + const examples = []; + const categories = await fs.readdir(destination); + const visit = async (pathLike, container) => { + const stat = await fs.lstat(pathLike); + if (stat.isDirectory()) { + if (await isSketch(pathLike)) { + container.sketches.push({ + name: path.basename(pathLike), + relativePath: path.relative(destination, pathLike), + }); + } else { + const names = await fs.readdir(pathLike); + for (const name of names) { + const childPath = path.join(pathLike, name); + if (await isSketch(childPath)) { + container.sketches.push({ + name, + relativePath: path.relative(destination, childPath), + }); + } else { + const child = { + label: name, + children: [], + sketches: [], + }; + container.children.push(child); + await visit(childPath, child); + } + } + } + } + }; + for (const category of categories) { + const example = { + label: category, + children: [], + sketches: [], + }; + await visit(path.join(destination, category), example); + examples.push(example); + } + await fs.writeFile( + path.join(destination, 'examples.json'), + JSON.stringify(examples, null, 2), + { encoding: 'utf8' } + ); + shell.echo(`Generated output to ${path.join(destination, 'examples.json')}`); })(); diff --git a/arduino-ide-extension/src/node/examples-service-impl.ts b/arduino-ide-extension/src/node/examples-service-impl.ts index 305f5e317..3f8e92dfb 100644 --- a/arduino-ide-extension/src/node/examples-service-impl.ts +++ b/arduino-ide-extension/src/node/examples-service-impl.ts @@ -25,6 +25,41 @@ import { duration } from '../common/decorators'; import { URI } from '@theia/core/lib/common/uri'; import { Path } from '@theia/core/lib/common/path'; +interface BuiltInSketchRef { + readonly name: string; + readonly relativePath: string; +} +namespace BuiltInSketchRef { + export function toSketchRef( + { name, relativePath }: BuiltInSketchRef, + root: URI + ): SketchRef { + return { + name, + uri: root.resolve(relativePath).toString(), + }; + } +} +interface BuiltInSketchContainer { + readonly label: string; + readonly children: BuiltInSketchContainer[]; + readonly sketches: BuiltInSketchRef[]; +} +namespace BuiltInSketchContainer { + export function toSketchContainer( + source: BuiltInSketchContainer, + root: URI + ): SketchContainer { + return { + label: source.label, + children: source.children.map((child) => toSketchContainer(child, root)), + sketches: source.sketches.map((child) => + BuiltInSketchRef.toSketchRef(child, root) + ), + }; + } +} + @injectable() export class ExamplesServiceImpl implements ExamplesService { @inject(SketchesServiceImpl) @@ -47,12 +82,15 @@ export class ExamplesServiceImpl implements ExamplesService { if (this._all) { return this._all; } - const exampleRootPath = join(__dirname, '..', '..', 'Examples'); - const exampleNames = await promisify(fs.readdir)(exampleRootPath); - this._all = await Promise.all( - exampleNames - .map((name) => join(exampleRootPath, name)) - .map((path) => this.load(path)) + const examplesRootPath = join(__dirname, '..', '..', 'Examples'); + const examplesRootUri = FileUri.create(examplesRootPath); + const rawJson = await fs.promises.readFile( + join(examplesRootPath, 'examples.json'), + { encoding: 'utf8' } + ); + const examples: BuiltInSketchContainer[] = JSON.parse(rawJson); + this._all = examples.map((container) => + BuiltInSketchContainer.toSketchContainer(container, examplesRootUri) ); return this._all; } From 5cecaabb03c5fe266756e523ab2dfb428e35032c Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Mon, 23 May 2022 16:23:38 +0200 Subject: [PATCH 11/45] load the list widget content only when activated. Signed-off-by: Akos Kitta --- .../src/browser/widgets/component-list/list-widget.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx index 061562724..d49a1865b 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx @@ -42,6 +42,11 @@ export abstract class ListWidget< protected readonly filterTextChangeEmitter = new Emitter< string | undefined >(); + /** + * Instead of running an `update` from the `postConstruct` `init` method, + * we use this variable to track first activate, then run. + */ + protected firstActivate = true; constructor(protected options: ListWidget.Options) { super(); @@ -61,7 +66,6 @@ export abstract class ListWidget< @postConstruct() protected init(): void { - this.update(); this.toDispose.pushAll([ this.notificationCenter.onIndexUpdated(() => this.refresh(undefined)), this.notificationCenter.onDaemonStarted(() => this.refresh(undefined)), @@ -74,6 +78,10 @@ export abstract class ListWidget< } protected override onActivateRequest(message: Message): void { + if (this.firstActivate) { + this.firstActivate = false; + this.update(); + } super.onActivateRequest(message); (this.focusNode || this.node).focus(); } From 6179300c728d7458d4b24d44aa5718a41c96a86d Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Mon, 23 May 2022 16:24:32 +0200 Subject: [PATCH 12/45] reimpl. discovering sketches from the sketchbook Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 2 +- .../src/node/sketches-service-impl.ts | 144 +++++++++++++++++- yarn.lock | 10 +- 3 files changed, 143 insertions(+), 13 deletions(-) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index ae8a6d9d6..9b7be28b2 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -44,7 +44,7 @@ "@types/btoa": "^1.2.3", "@types/dateformat": "^3.0.1", "@types/deepmerge": "^2.2.0", - "@types/glob": "^5.0.35", + "@types/glob": "^7.2.0", "@types/google-protobuf": "^3.7.2", "@types/js-yaml": "^3.12.2", "@types/keytar": "^4.4.0", diff --git a/arduino-ide-extension/src/node/sketches-service-impl.ts b/arduino-ide-extension/src/node/sketches-service-impl.ts index f35fdce45..f49b8aa69 100644 --- a/arduino-ide-extension/src/node/sketches-service-impl.ts +++ b/arduino-ide-extension/src/node/sketches-service-impl.ts @@ -24,14 +24,18 @@ import { ArchiveSketchRequest, LoadSketchRequest, } from './cli-protocol/cc/arduino/cli/commands/v1/commands_pb'; +import { duration } from '../common/decorators'; +import * as glob from 'glob'; const WIN32_DRIVE_REGEXP = /^[a-zA-Z]:\\/; const prefix = '.arduinoIDE-unsaved'; @injectable() -export class SketchesServiceImpl extends CoreClientAware - implements SketchesService { +export class SketchesServiceImpl + extends CoreClientAware + implements SketchesService +{ private sketchSuffixIndex = 1; private lastSketchBaseName: string; @@ -43,13 +47,147 @@ export class SketchesServiceImpl extends CoreClientAware @inject(EnvVariablesServer) protected readonly envVariableServer: EnvVariablesServer; + async getSketches({ uri, exclude, }: { uri?: string; exclude?: string[]; - }): Promise { + }): Promise { + const [old, _new] = await Promise.all([ + this.getSketchesOld({ uri, exclude }), + this.getSketchesNew({ uri, exclude }), + ]); + console.log(typeof old); + return _new; + } + + @duration() + async getSketchesNew({ + uri, + exclude, + }: { + uri?: string; + exclude?: string[]; + }): Promise { + const root = await this.root(uri); + const pathToAllSketchFiles = await new Promise( + (resolve, reject) => { + glob( + '/!(libraries|hardware)/**/*.{ino,pde}', + { root }, + (error, results) => { + if (error) { + reject(error); + } else { + resolve(results); + } + } + ); + } + ); + // Sort by path length to filter out nested sketches, such as the `Nested_folder` inside the `Folder` sketch. + // + // `directories#user` + // | + // +--Folder + // | + // +--Folder.ino + // | + // +--Nested_folder + // | + // +--Nested_folder.ino + pathToAllSketchFiles.sort((left, right) => left.length - right.length); + const container = SketchContainer.create( + uri ? path.basename(root) : 'Sketchbook' + ); + const getOrCreateChildContainer = ( + parent: SketchContainer, + segments: string[] + ) => { + if (segments.length === 1) { + throw new Error( + `Expected at least two segments relative path: ['ExampleSketchName', 'ExampleSketchName.{ino,pde}]. Was: ${segments}` + ); + } + if (segments.length === 2) { + return parent; + } + const label = segments[0]; + const existingSketch = parent.sketches.find( + (sketch) => sketch.name === label + ); + if (existingSketch) { + // If the container has a sketch with the same label, it cannot have a child container. + // See above example about how to ignore nested sketches. + return undefined; + } + let child = parent.children.find((child) => child.label === label); + if (!child) { + child = SketchContainer.create(label); + parent.children.push(child); + } + return child; + }; + for (const pathToSketchFile of pathToAllSketchFiles) { + const relative = path.relative(root, pathToSketchFile); + if (!relative) { + console.warn( + `Could not determine relative sketch path from the root <${root}> to the sketch <${pathToSketchFile}>. Skipping. Relative path was: ${relative}` + ); + continue; + } + const segments = relative.split(path.sep); + if (segments.length < 2) { + // folder name, and sketch name. + console.warn( + `Expected at least one segment relative path from the root <${root}> to the sketch <${pathToSketchFile}>. Skipping. Segments were: ${segments}.` + ); + continue; + } + // the folder name and the sketch name must match. For example, `Foo/foo.ino` is invalid. + // drop the folder name from the sketch name, if `.ino` or `.pde` remains, it's valid + const sketchName = segments[segments.length - 2]; + const sketchFilename = segments[segments.length - 1]; + const sketchFileExtension = segments[segments.length - 1].replace( + new RegExp(sketchName), + '' + ); + if (sketchFileExtension !== '.ino' && sketchFileExtension !== '.pde') { + console.warn( + `Mismatching sketch file <${sketchFilename} >and sketch folder name <${sketchName}>. Skipping` + ); + continue; + } + const child = getOrCreateChildContainer(container, segments); + if (child) { + child.sketches.push({ + name: sketchName, + uri: FileUri.create(pathToSketchFile).toString(), + }); + } + } + return container; + } + + private async root(uri?: string | undefined): Promise { + return FileUri.fsPath(uri ?? (await this.sketchbookUri())); + } + + private async sketchbookUri(): Promise { + const { sketchDirUri } = await this.configService.getConfiguration(); + return sketchDirUri; + } + + @duration() + async getSketchesOld({ + uri, + exclude, + }: { + uri?: string; + exclude?: string[]; + }): Promise { const start = Date.now(); let sketchbookPath: undefined | string; if (!uri) { diff --git a/yarn.lock b/yarn.lock index c22165fb6..cf1708f2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3126,7 +3126,7 @@ dependencies: "@types/node" "*" -"@types/glob@*", "@types/glob@^7.1.1": +"@types/glob@*", "@types/glob@^7.1.1", "@types/glob@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== @@ -3134,14 +3134,6 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/glob@^5.0.35": - version "5.0.37" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.37.tgz#d0982abc88f9aebbd62099d3d70440cbcea692de" - integrity sha512-ATA/xrS7CZ3A2WCPVY4eKdNpybq56zqlTirnHhhyOztZM/lPxJzusOBI3BsaXbu6FrUluqzvMlI4sZ6BDYMlMg== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - "@types/google-protobuf@^3.7.2": version "3.15.6" resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.6.tgz#674a69493ef2c849b95eafe69167ea59079eb504" From 17b564649bbeeffe4c65d91dda6e9a62c0ffd902 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Mon, 23 May 2022 16:25:50 +0200 Subject: [PATCH 13/45] dropped old way of calculating sketchbook content Signed-off-by: Akos Kitta --- arduino-ide-extension/src/node/sketches-service-impl.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arduino-ide-extension/src/node/sketches-service-impl.ts b/arduino-ide-extension/src/node/sketches-service-impl.ts index f49b8aa69..bac10fbe8 100644 --- a/arduino-ide-extension/src/node/sketches-service-impl.ts +++ b/arduino-ide-extension/src/node/sketches-service-impl.ts @@ -55,11 +55,10 @@ export class SketchesServiceImpl uri?: string; exclude?: string[]; }): Promise { - const [old, _new] = await Promise.all([ - this.getSketchesOld({ uri, exclude }), + const [/*old,*/ _new] = await Promise.all([ + // this.getSketchesOld({ uri, exclude }), this.getSketchesNew({ uri, exclude }), ]); - console.log(typeof old); return _new; } From 7e5be19419b7687b397f8d1d024857bbae2630bd Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Mon, 23 May 2022 18:41:54 +0200 Subject: [PATCH 14/45] fixed typo in logs. Signed-off-by: Akos Kitta --- arduino-ide-extension/src/node/sketches-service-impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino-ide-extension/src/node/sketches-service-impl.ts b/arduino-ide-extension/src/node/sketches-service-impl.ts index bac10fbe8..6725c6933 100644 --- a/arduino-ide-extension/src/node/sketches-service-impl.ts +++ b/arduino-ide-extension/src/node/sketches-service-impl.ts @@ -155,7 +155,7 @@ export class SketchesServiceImpl ); if (sketchFileExtension !== '.ino' && sketchFileExtension !== '.pde') { console.warn( - `Mismatching sketch file <${sketchFilename} >and sketch folder name <${sketchName}>. Skipping` + `Mismatching sketch file <${sketchFilename}> and sketch folder name <${sketchName}>. Skipping` ); continue; } From cf17ce189bfffe00f085b1f775f3399e1d41dc9a Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Mon, 23 May 2022 18:44:06 +0200 Subject: [PATCH 15/45] changed how to init cli config service. on daemon start, the port is broadcasted from BE. Signed-off-by: Akos Kitta --- .../browser/arduino-frontend-contribution.tsx | 12 +- .../src/browser/notification-center.ts | 12 +- .../theia/core/connection-status-service.ts | 38 ++++-- .../src/common/protocol/arduino-daemon.ts | 11 +- .../src/common/protocol/config-service.ts | 5 - .../common/protocol/notification-service.ts | 2 +- .../src/node/arduino-daemon-impl.ts | 37 +++-- arduino-ide-extension/src/node/cli-config.ts | 35 ++--- .../src/node/config-service-impl.ts | 129 ++++++------------ .../src/node/core-client-provider.ts | 16 ++- .../src/node/grpc-client-provider.ts | 43 +++--- .../src/node/notification-service-server.ts | 4 +- .../src/test/node/cli-config.test.ts | 5 - 13 files changed, 153 insertions(+), 196 deletions(-) diff --git a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx index 25e5d220a..510adf913 100644 --- a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx +++ b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx @@ -7,6 +7,7 @@ import { ExecutableService, Sketch, LibraryService, + ArduinoDaemon, } from '../common/protocol'; import { Mutex } from 'async-mutex'; import { @@ -172,6 +173,9 @@ export class ArduinoFrontendContribution @inject(IDEUpdaterDialog) protected readonly updaterDialog: IDEUpdaterDialog; + @inject(ArduinoDaemon) + protected readonly daemon: ArduinoDaemon; + protected invalidConfigPopup: | Promise | undefined; @@ -369,6 +373,10 @@ export class ArduinoFrontendContribution ): Promise { const release = await this.languageServerStartMutex.acquire(); try { + const port = this.daemon.tryGetPort(); + if (!port) { + return; + } await this.hostedPluginSupport.didStart; const details = await this.boardsService.getBoardDetails({ fqbn }); if (!details) { @@ -416,8 +424,6 @@ export class ArduinoFrontendContribution this.fileService.fsPath(new URI(lsUri)), ]); - const config = await this.configService.getConfiguration(); - this.languageServerFqbn = await Promise.race([ new Promise((_, reject) => setTimeout( @@ -429,7 +435,7 @@ export class ArduinoFrontendContribution 'arduino.languageserver.start', { lsPath, - cliDaemonAddr: `localhost:${config.daemon.port}`, // TODO: verify if this port is coming from the BE + cliDaemonAddr: `localhost:${port}`, clangdPath, log: currentSketchPath ? currentSketchPath : log, cliDaemonInstance: '1', diff --git a/arduino-ide-extension/src/browser/notification-center.ts b/arduino-ide-extension/src/browser/notification-center.ts index ab52f27ab..13ecd6041 100644 --- a/arduino-ide-extension/src/browser/notification-center.ts +++ b/arduino-ide-extension/src/browser/notification-center.ts @@ -1,4 +1,8 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import { Emitter } from '@theia/core/lib/common/event'; import { JsonRpcProxy } from '@theia/core/lib/common/messaging/proxy-factory'; import { DisposableCollection } from '@theia/core/lib/common/disposable'; @@ -23,7 +27,7 @@ export class NotificationCenter protected readonly server: JsonRpcProxy; protected readonly indexUpdatedEmitter = new Emitter(); - protected readonly daemonStartedEmitter = new Emitter(); + protected readonly daemonStartedEmitter = new Emitter(); protected readonly daemonStoppedEmitter = new Emitter(); protected readonly configChangedEmitter = new Emitter<{ config: Config | undefined; @@ -82,8 +86,8 @@ export class NotificationCenter this.indexUpdatedEmitter.fire(); } - notifyDaemonStarted(): void { - this.daemonStartedEmitter.fire(); + notifyDaemonStarted(port: string): void { + this.daemonStartedEmitter.fire(port); } notifyDaemonStopped(): void { diff --git a/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts b/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts index 64a3e93a7..ae997183f 100644 --- a/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts +++ b/arduino-ide-extension/src/browser/theia/core/connection-status-service.ts @@ -1,4 +1,8 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import { Disposable } from '@theia/core/lib/common/disposable'; import { StatusBarAlignment } from '@theia/core/lib/browser/status-bar/status-bar'; import { @@ -18,18 +22,22 @@ export class FrontendConnectionStatusService extends TheiaFrontendConnectionStat @inject(NotificationCenter) protected readonly notificationCenter: NotificationCenter; - protected isRunning = false; + protected connectedPort: string | undefined; @postConstruct() protected override async init(): Promise { this.schedulePing(); try { - this.isRunning = await this.daemon.isRunning(); + this.connectedPort = await this.daemon.tryGetPort(); } catch {} - this.notificationCenter.onDaemonStarted(() => (this.isRunning = true)); - this.notificationCenter.onDaemonStopped(() => (this.isRunning = false)); + this.notificationCenter.onDaemonStarted( + (port) => (this.connectedPort = port) + ); + this.notificationCenter.onDaemonStopped( + () => (this.connectedPort = undefined) + ); this.wsConnectionProvider.onIncomingMessageActivity(() => { - this.updateStatus(this.isRunning); + this.updateStatus(!!this.connectedPort); this.schedulePing(); }); } @@ -43,19 +51,23 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon @inject(NotificationCenter) protected readonly notificationCenter: NotificationCenter; - protected isRunning = false; + protected connectedPort: string | undefined; @postConstruct() protected async init(): Promise { try { - this.isRunning = await this.daemon.isRunning(); + this.connectedPort = await this.daemon.tryGetPort(); } catch {} - this.notificationCenter.onDaemonStarted(() => (this.isRunning = true)); - this.notificationCenter.onDaemonStopped(() => (this.isRunning = false)); + this.notificationCenter.onDaemonStarted( + (port) => (this.connectedPort = port) + ); + this.notificationCenter.onDaemonStopped( + () => (this.connectedPort = undefined) + ); } protected override onStateChange(state: ConnectionStatus): void { - if (!this.isRunning && state === ConnectionStatus.ONLINE) { + if (!this.connectedPort && state === ConnectionStatus.ONLINE) { return; } super.onStateChange(state); @@ -64,11 +76,11 @@ export class ApplicationConnectionStatusContribution extends TheiaApplicationCon protected override handleOffline(): void { this.statusBar.setElement('connection-status', { alignment: StatusBarAlignment.LEFT, - text: this.isRunning + text: this.connectedPort ? nls.localize('theia/core/offline', 'Offline') : '$(bolt) ' + nls.localize('theia/core/daemonOffline', 'CLI Daemon Offline'), - tooltip: this.isRunning + tooltip: this.connectedPort ? nls.localize( 'theia/core/cannotConnectBackend', 'Cannot connect to the backend.' diff --git a/arduino-ide-extension/src/common/protocol/arduino-daemon.ts b/arduino-ide-extension/src/common/protocol/arduino-daemon.ts index 783590048..696629923 100644 --- a/arduino-ide-extension/src/common/protocol/arduino-daemon.ts +++ b/arduino-ide-extension/src/common/protocol/arduino-daemon.ts @@ -1,6 +1,15 @@ export const ArduinoDaemonPath = '/services/arduino-daemon'; export const ArduinoDaemon = Symbol('ArduinoDaemon'); export interface ArduinoDaemon { - isRunning(): Promise; + /** + * Returns with a promise that resolves with the port + * of the CLI daemon when it's up and running. + */ getPort(): Promise; + /** + * Unlike `getPort` this method returns with a promise + * that resolves to `undefined` when the daemon is not running. + * Otherwise resolves to the CLI daemon port. + */ + tryGetPort(): Promise; } diff --git a/arduino-ide-extension/src/common/protocol/config-service.ts b/arduino-ide-extension/src/common/protocol/config-service.ts index b1c6285a1..adc5d9aa0 100644 --- a/arduino-ide-extension/src/common/protocol/config-service.ts +++ b/arduino-ide-extension/src/common/protocol/config-service.ts @@ -9,8 +9,6 @@ export interface ConfigService { getCliConfigFileUri(): Promise; getConfiguration(): Promise; setConfiguration(config: Config): Promise; - isInDataDir(uri: string): Promise; - isInSketchDir(uri: string): Promise; } export interface Daemon { @@ -115,10 +113,8 @@ export interface Config { readonly locale: string; readonly sketchDirUri: string; readonly dataDirUri: string; - readonly downloadsDirUri: string; readonly additionalUrls: AdditionalUrls; readonly network: Network; - readonly daemon: Daemon; } export namespace Config { export function sameAs(left: Config, right: Config): boolean { @@ -135,7 +131,6 @@ export namespace Config { return ( left.locale === right.locale && left.dataDirUri === right.dataDirUri && - left.downloadsDirUri === right.downloadsDirUri && left.sketchDirUri === right.sketchDirUri && Network.sameAs(left.network, right.network) ); diff --git a/arduino-ide-extension/src/common/protocol/notification-service.ts b/arduino-ide-extension/src/common/protocol/notification-service.ts index 59cef1886..3e33f727e 100644 --- a/arduino-ide-extension/src/common/protocol/notification-service.ts +++ b/arduino-ide-extension/src/common/protocol/notification-service.ts @@ -9,7 +9,7 @@ import { export interface NotificationServiceClient { notifyIndexUpdated(): void; - notifyDaemonStarted(): void; + notifyDaemonStarted(port: string): void; notifyDaemonStopped(): void; notifyConfigChanged(event: { config: Config | undefined }): void; notifyPlatformInstalled(event: { item: BoardsPackage }): void; diff --git a/arduino-ide-extension/src/node/arduino-daemon-impl.ts b/arduino-ide-extension/src/node/arduino-daemon-impl.ts index 7744cd6ea..f3995fd1d 100644 --- a/arduino-ide-extension/src/node/arduino-daemon-impl.ts +++ b/arduino-ide-extension/src/node/arduino-daemon-impl.ts @@ -32,13 +32,12 @@ export class ArduinoDaemonImpl protected readonly notificationService: NotificationServiceServer; protected readonly toDispose = new DisposableCollection(); - protected readonly onDaemonStartedEmitter = new Emitter(); + protected readonly onDaemonStartedEmitter = new Emitter(); protected readonly onDaemonStoppedEmitter = new Emitter(); protected _running = false; - protected _ready = new Deferred(); + protected _port = new Deferred(); protected _execPath: string | undefined; - protected _port: string; // Backend application lifecycle. @@ -48,12 +47,15 @@ export class ArduinoDaemonImpl // Daemon API - async isRunning(): Promise { - return Promise.resolve(this._running); + async getPort(): Promise { + return this._port.promise; } - async getPort(): Promise { - return Promise.resolve(this._port); + async tryGetPort(): Promise { + if (this._running) { + return this._port.promise; + } + return undefined; } async startDaemon(): Promise { @@ -62,7 +64,6 @@ export class ArduinoDaemonImpl const cliPath = await this.getExecPath(); this.onData(`Starting daemon from ${cliPath}...`); const { daemon, port } = await this.spawnDaemonProcess(); - this._port = port; // Watchdog process for terminating the daemon process when the backend app terminates. spawn( process.execPath, @@ -83,7 +84,7 @@ export class ArduinoDaemonImpl Disposable.create(() => daemon.kill()), Disposable.create(() => this.fireDaemonStopped()), ]); - this.fireDaemonStarted(); + this.fireDaemonStarted(port); this.onData('Daemon is running.'); } catch (err) { this.onData('Failed to start the daemon.'); @@ -103,7 +104,7 @@ export class ArduinoDaemonImpl this.toDispose.dispose(); } - get onDaemonStarted(): Event { + get onDaemonStarted(): Event { return this.onDaemonStartedEmitter.event; } @@ -111,10 +112,6 @@ export class ArduinoDaemonImpl return this.onDaemonStoppedEmitter.event; } - get ready(): Promise { - return this._ready.promise; - } - async getExecPath(): Promise { if (this._execPath) { return this._execPath; @@ -240,11 +237,11 @@ export class ArduinoDaemonImpl return ready.promise; } - protected fireDaemonStarted(): void { + protected fireDaemonStarted(port: string): void { this._running = true; - this._ready.resolve(); - this.onDaemonStartedEmitter.fire(); - this.notificationService.notifyDaemonStarted(); + this._port.resolve(port); + this.onDaemonStartedEmitter.fire(port); + this.notificationService.notifyDaemonStarted(port); } protected fireDaemonStopped(): void { @@ -252,8 +249,8 @@ export class ArduinoDaemonImpl return; } this._running = false; - this._ready.reject(); // Reject all pending. - this._ready = new Deferred(); + this._port.reject(); // Reject all pending. + this._port = new Deferred(); this.onDaemonStoppedEmitter.fire(); this.notificationService.notifyDaemonStopped(); } diff --git a/arduino-ide-extension/src/node/cli-config.ts b/arduino-ide-extension/src/node/cli-config.ts index 1b19557af..16bac01a3 100644 --- a/arduino-ide-extension/src/node/cli-config.ts +++ b/arduino-ide-extension/src/node/cli-config.ts @@ -1,42 +1,31 @@ import { RecursivePartial } from '@theia/core/lib/common/types'; -import { Daemon } from '../common/protocol/config-service'; +import { AdditionalUrls } from '../common/protocol'; export const CLI_CONFIG = 'arduino-cli.yaml'; export interface BoardManager { - readonly additional_urls: Array; + readonly additional_urls: AdditionalUrls; } export namespace BoardManager { export function sameAs( left: RecursivePartial | undefined, right: RecursivePartial | undefined ): boolean { - const leftOrDefault = left || {}; - const rightOrDefault = right || {}; - const leftUrls = Array.from(new Set(leftOrDefault.additional_urls || [])); - const rightUrls = Array.from(new Set(rightOrDefault.additional_urls || [])); - if (leftUrls.length !== rightUrls.length) { - return false; - } - return leftUrls.every((url) => rightUrls.indexOf(url) !== -1); + const leftUrls = left?.additional_urls ?? []; + const rightUrls = right?.additional_urls ?? []; + return AdditionalUrls.sameAs(leftUrls, rightUrls); } } export interface Directories { readonly data: string; - readonly downloads: string; readonly user: string; } export namespace Directories { export function is( directories: RecursivePartial | undefined ): directories is Directories { - return ( - !!directories && - !!directories.data && - !!directories.downloads && - !!directories.user - ); + return !!directories && !!directories.data && !!directories.user; } export function sameAs( left: RecursivePartial | undefined, @@ -48,11 +37,7 @@ export namespace Directories { if (right === undefined) { return left === undefined; } - return ( - left.data === right.data && - left.downloads === right.downloads && - left.user === right.user - ); + return left.data === right.data && left.user === right.user; } } @@ -111,15 +96,12 @@ export interface CliConfig { // Bare minimum required CLI config. export interface DefaultCliConfig extends CliConfig { directories: Directories; - daemon: Daemon; } export namespace DefaultCliConfig { export function is( config: RecursivePartial | undefined ): config is DefaultCliConfig { - return ( - !!config && Directories.is(config.directories) && Daemon.is(config.daemon) - ); + return !!config && Directories.is(config.directories); } export function sameAs( left: DefaultCliConfig, @@ -127,7 +109,6 @@ export namespace DefaultCliConfig { ): boolean { return ( Directories.sameAs(left.directories, right.directories) && - Daemon.sameAs(left.daemon, right.daemon) && BoardManager.sameAs(left.board_manager, right.board_manager) && Logging.sameAs(left.logging, right.logging) ); diff --git a/arduino-ide-extension/src/node/config-service-impl.ts b/arduino-ide-extension/src/node/config-service-impl.ts index 3e626f4c1..420d4185f 100644 --- a/arduino-ide-extension/src/node/config-service-impl.ts +++ b/arduino-ide-extension/src/node/config-service-impl.ts @@ -1,8 +1,6 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import * as temp from 'temp'; +import { promises as fs } from 'fs'; +import { dirname } from 'path'; import * as yaml from 'js-yaml'; -import { promisify } from 'util'; import * as grpc from '@grpc/grpc-js'; import { injectable, inject, named } from '@theia/core/shared/inversify'; import URI from '@theia/core/lib/common/uri'; @@ -28,9 +26,9 @@ import { DefaultCliConfig, CLI_CONFIG } from './cli-config'; import { Deferred } from '@theia/core/lib/common/promise-util'; import { EnvVariablesServer } from '@theia/core/lib/common/env-variables'; import { deepClone } from '@theia/core'; +import { duration } from '../common/decorators'; const deepmerge = require('deepmerge'); -const track = temp.track(); @injectable() export class ConfigServiceImpl @@ -54,18 +52,19 @@ export class ConfigServiceImpl protected ready = new Deferred(); protected readonly configChangeEmitter = new Emitter(); - async onStart(): Promise { - await this.ensureCliConfigExists(); - this.cliConfig = await this.loadCliConfig(); - if (this.cliConfig) { - const config = await this.mapCliConfigToAppConfig(this.cliConfig); - if (config) { - this.config = config; - this.ready.resolve(); - return; + onStart(): void { + this.loadCliConfig().then(async (cliConfig) => { + this.cliConfig = cliConfig; + if (this.cliConfig) { + const config = await this.mapCliConfigToAppConfig(this.cliConfig); + if (config) { + this.config = config; + this.ready.resolve(); + return; + } } - } - this.fireInvalidConfig(); + this.fireInvalidConfig(); + }); } async getCliConfigFileUri(): Promise { @@ -75,8 +74,7 @@ export class ConfigServiceImpl async getConfiguration(): Promise { await this.ready.promise; - await this.daemon.ready; - return { ...this.config, daemon: { port: await this.daemon.getPort() } }; + return { ...this.config }; } // Used by frontend to update the config. @@ -91,17 +89,10 @@ export class ConfigServiceImpl if (!copyDefaultCliConfig) { copyDefaultCliConfig = await this.getFallbackCliConfig(); } - const { - additionalUrls, - dataDirUri, - downloadsDirUri, - sketchDirUri, - network, - locale, - } = config; + const { additionalUrls, dataDirUri, sketchDirUri, network, locale } = + config; copyDefaultCliConfig.directories = { data: FileUri.fsPath(dataDirUri), - downloads: FileUri.fsPath(downloadsDirUri), user: FileUri.fsPath(sketchDirUri), }; copyDefaultCliConfig.board_manager = { @@ -135,76 +126,44 @@ export class ConfigServiceImpl return this.daemon.getVersion(); } - async isInDataDir(uri: string): Promise { - return this.getConfiguration().then(({ dataDirUri }) => - new URI(dataDirUri).isEqualOrParent(new URI(uri)) - ); - } - - async isInSketchDir(uri: string): Promise { - return this.getConfiguration().then(({ sketchDirUri }) => - new URI(sketchDirUri).isEqualOrParent(new URI(uri)) - ); - } - - protected async loadCliConfig(): Promise { + @duration() + protected async loadCliConfig( + initializeIfAbsent = true + ): Promise { const cliConfigFileUri = await this.getCliConfigFileUri(); const cliConfigPath = FileUri.fsPath(cliConfigFileUri); try { - const content = await promisify(fs.readFile)(cliConfigPath, { + const content = await fs.readFile(cliConfigPath, { encoding: 'utf8', }); - const model = yaml.safeLoad(content) || {}; - // The CLI can run with partial (missing `port`, `directories`), the app cannot, we merge the default with the user's config. + const model = (yaml.safeLoad(content) || {}) as DefaultCliConfig; + if (model.directories.data && model.directories.user) { + return model; + } + // The CLI can run with partial (missing `port`, `directories`), the IDE2 cannot. + // We merge the default CLI config with the partial user's config. const fallbackModel = await this.getFallbackCliConfig(); return deepmerge(fallbackModel, model) as DefaultCliConfig; } catch (error) { - this.logger.error( - `Error occurred when loading CLI config from ${cliConfigPath}.`, - error - ); + if ('code' in error && error.code === 'ENOENT') { + if (initializeIfAbsent) { + await this.initCliConfigTo(dirname(cliConfigPath)); + return this.loadCliConfig(false); + } + } + throw error; } - return undefined; } protected async getFallbackCliConfig(): Promise { const cliPath = await this.daemon.getExecPath(); - const throwawayDirPath = await new Promise((resolve, reject) => { - track.mkdir({}, (err, dirPath) => { - if (err) { - reject(err); - return; - } - resolve(dirPath); - }); - }); - await spawnCommand(`"${cliPath}"`, [ + const rawJson = await spawnCommand(`"${cliPath}"`, [ 'config', - 'init', - '--dest-dir', - `"${throwawayDirPath}"`, + 'dump', + 'format', + '--json', ]); - const rawYaml = await promisify(fs.readFile)( - path.join(throwawayDirPath, CLI_CONFIG), - { encoding: 'utf-8' } - ); - const model = yaml.safeLoad(rawYaml.trim()); - return model as DefaultCliConfig; - } - - protected async ensureCliConfigExists(): Promise { - const cliConfigFileUri = await this.getCliConfigFileUri(); - const cliConfigPath = FileUri.fsPath(cliConfigFileUri); - let exists = await promisify(fs.exists)(cliConfigPath); - if (!exists) { - await this.initCliConfigTo(path.dirname(cliConfigPath)); - exists = await promisify(fs.exists)(cliConfigPath); - if (!exists) { - throw new Error( - `Could not initialize the default CLI configuration file at ${cliConfigPath}.` - ); - } - } + return JSON.parse(rawJson); } protected async initCliConfigTo(fsPathToDir: string): Promise { @@ -220,8 +179,8 @@ export class ConfigServiceImpl protected async mapCliConfigToAppConfig( cliConfig: DefaultCliConfig ): Promise { - const { directories, locale = 'en', daemon } = cliConfig; - const { data, user, downloads } = directories; + const { directories, locale = 'en' } = cliConfig; + const { user, data } = directories; const additionalUrls: Array = []; if (cliConfig.board_manager && cliConfig.board_manager.additional_urls) { additionalUrls.push( @@ -232,11 +191,9 @@ export class ConfigServiceImpl return { dataDirUri: FileUri.create(data).toString(), sketchDirUri: FileUri.create(user).toString(), - downloadsDirUri: FileUri.create(downloads).toString(), additionalUrls, network, locale, - daemon, }; } diff --git a/arduino-ide-extension/src/node/core-client-provider.ts b/arduino-ide-extension/src/node/core-client-provider.ts index 1fce98805..73922d9ce 100644 --- a/arduino-ide-extension/src/node/core-client-provider.ts +++ b/arduino-ide-extension/src/node/core-client-provider.ts @@ -1,5 +1,9 @@ import * as grpc from '@grpc/grpc-js'; -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import { Event, Emitter } from '@theia/core/lib/common/event'; import { GrpcClientProvider } from './grpc-client-provider'; import { ArduinoCoreServiceClient } from './cli-protocol/cc/arduino/cli/commands/v1/commands_grpc_pb'; @@ -48,9 +52,7 @@ export class CoreClientProvider extends GrpcClientProvider(); } - protected override async reconcileClient(): Promise { - const port = await this.daemon.getPort(); - + protected override async reconcileClient(port: string): Promise { if (port && port === this._port) { // No need to create a new gRPC client, but we have to update the indexes. if (this._client && !(this._client instanceof Error)) { @@ -58,18 +60,18 @@ export class CoreClientProvider extends GrpcClientProvider { - this.daemon.ready.then(async () => { + this.daemon.getPort().then(async (port) => { // First create the client and the instance synchronously // and notify client is ready. // TODO: Creation failure should probably be handled here - await this.reconcileClient().then(() => { + await this.reconcileClient(port).then(() => { this._created.resolve(); }); diff --git a/arduino-ide-extension/src/node/grpc-client-provider.ts b/arduino-ide-extension/src/node/grpc-client-provider.ts index af1fcede6..10d7b3d70 100644 --- a/arduino-ide-extension/src/node/grpc-client-provider.ts +++ b/arduino-ide-extension/src/node/grpc-client-provider.ts @@ -1,4 +1,8 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import { ILogger } from '@theia/core/lib/common/logger'; import { MaybePromise } from '@theia/core/lib/common/types'; import { ConfigServiceImpl } from './config-service-impl'; @@ -15,16 +19,18 @@ export abstract class GrpcClientProvider { @inject(ConfigServiceImpl) protected readonly configService: ConfigServiceImpl; - protected _port: string | number | undefined; + protected _port: string | undefined; protected _client: C | Error | undefined; @postConstruct() protected init(): void { - const updateClient = () => { - this.reconcileClient(); - }; - this.configService.onConfigChange(updateClient); - this.daemon.ready.then(updateClient); + this.configService.onConfigChange(() => { + // Only reconcile the gRPC client if the port is known. Hence the CLI daemon is running. + if (this._port) { + this.reconcileClient(this._port); + } + }); + this.daemon.getPort().then((port) => this.reconcileClient(port)); this.daemon.onDaemonStopped(() => { if (this._client && !(this._client instanceof Error)) { this.close(this._client); @@ -36,32 +42,25 @@ export abstract class GrpcClientProvider { async client(): Promise { try { - await this.daemon.ready; + await this.daemon.getPort(); return this._client; } catch (error) { return error; } } - protected async reconcileClient(): Promise { - const port = await this.daemon.getPort(); - - if (this._port === port) { - return; // Nothing to do. - } + protected async reconcileClient(port: string): Promise { this._port = port; if (this._client && !(this._client instanceof Error)) { this.close(this._client); this._client = undefined; } - if (this._port) { - try { - const client = await this.createClient(this._port); - this._client = client; - } catch (error) { - this.logger.error('Could not create client for gRPC.', error); - this._client = error; - } + try { + const client = await this.createClient(this._port); + this._client = client; + } catch (error) { + this.logger.error('Could not create client for gRPC.', error); + this._client = error; } } diff --git a/arduino-ide-extension/src/node/notification-service-server.ts b/arduino-ide-extension/src/node/notification-service-server.ts index 7ce211eca..851452d38 100644 --- a/arduino-ide-extension/src/node/notification-service-server.ts +++ b/arduino-ide-extension/src/node/notification-service-server.ts @@ -19,8 +19,8 @@ export class NotificationServiceServerImpl this.clients.forEach((client) => client.notifyIndexUpdated()); } - notifyDaemonStarted(): void { - this.clients.forEach((client) => client.notifyDaemonStarted()); + notifyDaemonStarted(port: string): void { + this.clients.forEach((client) => client.notifyDaemonStarted(port)); } notifyDaemonStopped(): void { diff --git a/arduino-ide-extension/src/test/node/cli-config.test.ts b/arduino-ide-extension/src/test/node/cli-config.test.ts index d21f56879..3d09ef2ee 100644 --- a/arduino-ide-extension/src/test/node/cli-config.test.ts +++ b/arduino-ide-extension/src/test/node/cli-config.test.ts @@ -19,7 +19,6 @@ describe('cli-config', () => { [ () => { const conf = defaultConfig(); - (conf.daemon as any).port = String(conf.daemon.port); return conf; }, defaultConfig, @@ -41,12 +40,8 @@ describe('cli-config', () => { board_manager: { additional_urls: [], }, - daemon: { - port: 5000, - }, directories: { data: 'data', - downloads: 'downloads', user: 'user', }, }; From 61279fe18a36638589f726cc5af542ed9bc367d7 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 09:42:53 +0200 Subject: [PATCH 16/45] run update after show. Signed-off-by: Akos Kitta --- .../browser/widgets/component-list/list-widget.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx index d49a1865b..f28db5d5b 100644 --- a/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/component-list/list-widget.tsx @@ -21,7 +21,7 @@ import { NotificationCenter } from '../../notification-center'; @injectable() export abstract class ListWidget< T extends ArduinoComponent -> extends ReactWidget { + > extends ReactWidget { @inject(MessageService) protected readonly messageService: MessageService; @@ -77,11 +77,20 @@ export abstract class ListWidget< return this.deferredContainer.promise; } - protected override onActivateRequest(message: Message): void { + protected override onAfterShow(message: Message): void { + this.maybeUpdateOnFirstRender(); + super.onAfterShow(message); + } + + private maybeUpdateOnFirstRender() { if (this.firstActivate) { this.firstActivate = false; this.update(); } + } + + protected override onActivateRequest(message: Message): void { + this.maybeUpdateOnFirstRender(); super.onActivateRequest(message); (this.focusNode || this.node).focus(); } From 3e583a7fdede58dabc05a179011b36de5ea24a20 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 10:44:52 +0200 Subject: [PATCH 17/45] fall back to new temp sketch URI when no recent WS Signed-off-by: Akos Kitta --- .../theia/core/frontend-application.ts | 10 ++-- .../theia/workspace/workspace-service.ts | 3 +- .../workspace/default-workspace-server.ts | 51 ++++++++++++++++--- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/arduino-ide-extension/src/browser/theia/core/frontend-application.ts b/arduino-ide-extension/src/browser/theia/core/frontend-application.ts index 766ef1bb0..ba6b2f8bc 100644 --- a/arduino-ide-extension/src/browser/theia/core/frontend-application.ts +++ b/arduino-ide-extension/src/browser/theia/core/frontend-application.ts @@ -22,17 +22,15 @@ export class FrontendApplication extends TheiaFrontendApplication { protected override async initializeLayout(): Promise { await super.initializeLayout(); - const roots = await this.workspaceService.roots; - for (const root of roots) { - const exists = await this.fileService.exists(root.resource); - if (exists) { - this.sketchesService.markAsRecentlyOpened(root.resource.toString()); // no await, will get the notification later and rebuild the menu + this.workspaceService.roots.then(async (roots) => { + for (const root of roots) { await this.commandService.executeCommand( ArduinoCommands.OPEN_SKETCH_FILES.id, root.resource ); + this.sketchesService.markAsRecentlyOpened(root.resource.toString()); // no await, will get the notification later and rebuild the menu } - } + }); } protected override getStartupIndicator( diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts index 86c998ea1..27f08f7f3 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-service.ts @@ -72,11 +72,12 @@ export class WorkspaceService extends TheiaWorkspaceService { // Remove the leading # and decode the URI. const wpPath = decodeURI(window.location.hash.substring(1)); const workspaceUri = new URI().withPath(wpPath).withScheme('file'); - // Customization! Here, we do no check if the workspace exists. + // ### Customization! Here, we do no check if the workspace exists. return workspaceUri.toString(); } else { // Else, ask the server for its suggested workspace (usually the one // specified on the CLI, or the most recent). + // ### Customization! the default workspace server will create a new sketch and will return with its URI if no recent workspaces are available. return this.server.getMostRecentlyUsedWorkspace(); } } diff --git a/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts b/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts index de25e7e89..3481f7de1 100644 --- a/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts +++ b/arduino-ide-extension/src/node/theia/workspace/default-workspace-server.ts @@ -1,7 +1,10 @@ +import { promises as fs, constants } from 'fs'; import { injectable, inject } from '@theia/core/shared/inversify'; import { ILogger } from '@theia/core/lib/common/logger'; import { DefaultWorkspaceServer as TheiaDefaultWorkspaceServer } from '@theia/workspace/lib/node/default-workspace-server'; import { ConfigService } from '../../../common/protocol/config-service'; +import { SketchesService } from '../../../common/protocol'; +import { FileUri } from '@theia/core/lib/node'; @injectable() export class DefaultWorkspaceServer extends TheiaDefaultWorkspaceServer { @@ -11,13 +14,49 @@ export class DefaultWorkspaceServer extends TheiaDefaultWorkspaceServer { @inject(ILogger) protected readonly logger: ILogger; - protected override async getWorkspaceURIFromCli(): Promise { + @inject(SketchesService) + private readonly sketchesService: SketchesService; + + override async onStart(): Promise { + // NOOP + // No need to remove untitled workspaces. IDE2 does not use workspaces. + } + + override async getMostRecentlyUsedWorkspace(): Promise { + const uri = await super.getMostRecentlyUsedWorkspace(); + if (!uri) { + const { uri } = await this.sketchesService.createNewSketch(); + return uri; + } + return uri; + } + + /** + * This is the async re-implementation of the default Theia behavior. + */ + override async getRecentWorkspaces(): Promise { + const listUri: string[] = []; + const data = await this.readRecentWorkspacePathsFromUserHome(); + if (data && data.recentRoots) { + await Promise.all( + data.recentRoots + .filter((element) => Boolean(element)) + .map(async (element) => { + if (await this.exists(element)) { + listUri.push(element); + } + }) + ); + } + return listUri; + } + + private async exists(uri: string): Promise { try { - const config = await this.configService.getConfiguration(); - return config.sketchDirUri; - } catch (err) { - this.logger.error(`Failed to determine the sketch directory: ${err}`); - return super.getWorkspaceURIFromCli(); + await fs.access(FileUri.fsPath(uri), constants.R_OK | constants.W_OK); + return true; + } catch { + return false; } } } From d5fabc1535dcb2a5e26c73f9646194d515ac57be Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 11:06:56 +0200 Subject: [PATCH 18/45] customized JSON schema store, editor navigation history, and preference tree generator. Signed-off-by: Akos Kitta --- .../browser/arduino-ide-frontend-module.ts | 21 +++++++++++++++++++ .../browser/theia/core/json-schema-store.ts | 11 ++++++++++ .../editor/editor-navigation-contribution.ts | 11 ++++++++++ .../preferences/preference-tree-generator.ts | 17 +++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 arduino-ide-extension/src/browser/theia/core/json-schema-store.ts create mode 100644 arduino-ide-extension/src/browser/theia/editor/editor-navigation-contribution.ts create mode 100644 arduino-ide-extension/src/browser/theia/preferences/preference-tree-generator.ts diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 081d06d54..5a67e3a74 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -271,6 +271,12 @@ import { IDEUpdaterDialogWidget, } from './dialogs/ide-updater/ide-updater-dialog'; import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-provider'; +import { DefaultJsonSchemaContribution } from './theia/core/json-schema-store'; +import { DefaultJsonSchemaContribution as TheiaDefaultJsonSchemaContribution } from '@theia/core/lib/browser/json-schema-store'; +import { EditorNavigationContribution } from './theia/editor/editor-navigation-contribution'; +import { EditorNavigationContribution as TheiaEditorNavigationContribution } from '@theia/editor/lib/browser/editor-navigation-contribution'; +import { PreferenceTreeGenerator } from './theia/preferences/preference-tree-generator'; +import { PreferenceTreeGenerator as TheiaPreferenceTreeGenerator } from '@theia/preferences/lib/browser/util/preference-tree-generator'; MonacoThemingService.register({ id: 'arduino-theme', @@ -669,6 +675,21 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(NavigatorTabBarDecorator).toSelf().inSingletonScope(); rebind(TheiaNavigatorTabBarDecorator).toService(NavigatorTabBarDecorator); + // Do not fetch the `catalog.json` from Azure on FE load. + bind(DefaultJsonSchemaContribution).toSelf().inSingletonScope(); + rebind(TheiaDefaultJsonSchemaContribution).toService( + DefaultJsonSchemaContribution + ); + + // Do not block the app startup when initializing the editor navigation history. + bind(EditorNavigationContribution).toSelf().inSingletonScope(); + rebind(TheiaEditorNavigationContribution).toService( + EditorNavigationContribution + ); + + bind(PreferenceTreeGenerator).toSelf().inSingletonScope() + rebind(TheiaPreferenceTreeGenerator).toService(PreferenceTreeGenerator); + // To avoid running `Save All` when there are no dirty editors before starting the debug session. bind(DebugSessionManager).toSelf().inSingletonScope(); rebind(TheiaDebugSessionManager).toService(DebugSessionManager); diff --git a/arduino-ide-extension/src/browser/theia/core/json-schema-store.ts b/arduino-ide-extension/src/browser/theia/core/json-schema-store.ts new file mode 100644 index 000000000..8d9f96313 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/json-schema-store.ts @@ -0,0 +1,11 @@ +import { injectable } from '@theia/core/shared/inversify'; +import { DefaultJsonSchemaContribution as TheiaDefaultJsonSchemaContribution } from '@theia/core/lib/browser/json-schema-store'; + +@injectable() +export class DefaultJsonSchemaContribution extends TheiaDefaultJsonSchemaContribution { + override async registerSchemas(): Promise { + // NOOP + // Do not fetch the https://www.schemastore.org/api/json/catalog.json on every single browser window load. + // If the schemas are required in the future, we should fetch the `catalog.json` on build time and load it. + } +} diff --git a/arduino-ide-extension/src/browser/theia/editor/editor-navigation-contribution.ts b/arduino-ide-extension/src/browser/theia/editor/editor-navigation-contribution.ts new file mode 100644 index 000000000..ebd90f1bf --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/editor/editor-navigation-contribution.ts @@ -0,0 +1,11 @@ +import { injectable } from '@theia/core/shared/inversify'; +import { EditorNavigationContribution as TheiaEditorNavigationContribution } from '@theia/editor/lib/browser/editor-navigation-contribution'; + +@injectable() +export class EditorNavigationContribution extends TheiaEditorNavigationContribution { + override async onStart(): Promise { + // No await. + // Restore the navigation history asynchronously. + super.onStart(); + } +} diff --git a/arduino-ide-extension/src/browser/theia/preferences/preference-tree-generator.ts b/arduino-ide-extension/src/browser/theia/preferences/preference-tree-generator.ts new file mode 100644 index 000000000..0dcb7af66 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/preferences/preference-tree-generator.ts @@ -0,0 +1,17 @@ +import { CompositeTreeNode } from '@theia/core/lib/browser/tree/tree'; +import { injectable } from '@theia/core/shared/inversify'; +import { PreferenceTreeGenerator as TheiaPreferenceTreeGenerator } from '@theia/preferences/lib/browser/util/preference-tree-generator'; + +@injectable() +export class PreferenceTreeGenerator extends TheiaPreferenceTreeGenerator { + protected override async init(): Promise { + // The IDE2 does not use the default Theia preferences UI. + // There is no need to create and keep the the tree model synchronized when there is no UI for it. + } + + // Just returns with the empty root. + override generateTree(): CompositeTreeNode { + this._root = this.createRootNode(); + return this._root; + } +} From fdca52423656c9df8a8abea2b0d82a65bc749e7c Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 13:39:59 +0200 Subject: [PATCH 19/45] launch config to start with dev tools + w/o splash Signed-off-by: Akos Kitta --- .vscode/launch.json | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index aa726a434..3ab3ee582 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,13 +4,12 @@ { "type": "node", "request": "launch", - "name": "App (Electron)", + "name": "App (Electron) [Dev]", "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron", "windows": { "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd", }, "cwd": "${workspaceFolder}/electron-app", - "protocol": "inspector", "args": [ ".", "--log-level=debug", @@ -21,7 +20,43 @@ "--no-app-auto-install", "--plugins=local-dir:../plugins", "--hosted-plugin-inspect=9339", - "--nosplash" + "--nosplash", + "--open-devtools" + ], + "env": { + "NODE_ENV": "development" + }, + "sourceMaps": true, + "outFiles": [ + "${workspaceRoot}/electron-app/src-gen/backend/*.js", + "${workspaceRoot}/electron-app/src-gen/frontend/*.js", + "${workspaceRoot}/electron-app/lib/**/*.js", + "${workspaceRoot}/arduino-ide-extension/lib/**/*.js", + "${workspaceRoot}/node_modules/@theia/**/*.js" + ], + "smartStep": true, + "internalConsoleOptions": "openOnSessionStart", + "outputCapture": "std" + }, + { + "type": "node", + "request": "launch", + "name": "App (Electron)", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron", + "windows": { + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd", + }, + "cwd": "${workspaceFolder}/electron-app", + "args": [ + ".", + "--log-level=debug", + "--hostname=localhost", + "--no-cluster", + "--app-project-path=${workspaceRoot}/electron-app", + "--remote-debugging-port=9222", + "--no-app-auto-install", + "--plugins=local-dir:../plugins", + "--hosted-plugin-inspect=9339" ], "env": { "NODE_ENV": "development" @@ -79,7 +114,6 @@ { "type": "node", "request": "launch", - "protocol": "inspector", "name": "Run Test [current]", "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", "args": [ From dbf635a26699bb6dc9258a6027bb4d18f8c29f0a Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 13:42:10 +0200 Subject: [PATCH 20/45] defer all menu updates before app is ready. Signed-off-by: Akos Kitta --- .../theia/core/electron-main-menu-factory.ts | 31 +++++++++++++++++-- .../theia/core/electron-menu-contribution.ts | 26 ++++++++++++++-- .../theia/core/electron-menu-module.ts | 2 +- .../theia/electron-main-application.ts | 18 +++++++++++ 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts index 046ebe926..f18b07df8 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-main-menu-factory.ts @@ -1,4 +1,4 @@ -import { injectable } from '@theia/core/shared/inversify'; +import { inject, injectable } from '@theia/core/shared/inversify'; import * as remote from '@theia/core/electron-shared/@electron/remote'; import { isOSX } from '@theia/core/lib/common/os'; import { @@ -14,9 +14,26 @@ import { ArduinoMenus, PlaceholderMenuNode, } from '../../../browser/menu/arduino-menus'; +import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; @injectable() export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { + @inject(FrontendApplicationStateService) + private readonly appStateService: FrontendApplicationStateService; + + private appReady = false; + private updateWhenReady = false; + + override postConstruct(): void { + super.postConstruct(); + this.appStateService.reachedState('ready').then(() => { + this.appReady = true; + if (this.updateWhenReady) { + this.setMenuBar(); + } + }); + } + override createElectronMenuBar(): Electron.Menu { this._toggledCommands.clear(); // https://github.com/eclipse-theia/theia/issues/8977 const menuModel = this.menuProvider.getMenu(MAIN_MENU_BAR); @@ -30,6 +47,13 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { } override async setMenuBar(): Promise { + // Avoid updating menu items when the app is not ready. + // Getting the current electron window is not free and synchronous. + // Here, we defer all menu update requests, and fire one when the app is ready. + if (!this.appReady) { + this.updateWhenReady = true; + return; + } await this.preferencesService.ready; const createdMenuBar = this.createElectronMenuBar(); if (isOSX) { @@ -39,7 +63,10 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory { } } - override createElectronContextMenu(menuPath: MenuPath, args?: any[]): Electron.Menu { + override createElectronContextMenu( + menuPath: MenuPath, + args?: any[] + ): Electron.Menu { const menuModel = this.menuProvider.getMenu(menuPath); const template = this.fillMenuTemplate([], menuModel, args, { showDisabled: false, diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts index 924051611..4aa1cb462 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts @@ -1,4 +1,4 @@ -import { injectable } from '@theia/core/shared/inversify'; +import { inject, injectable } from '@theia/core/shared/inversify'; import { CommandRegistry } from '@theia/core/lib/common/command'; import { MenuModelRegistry } from '@theia/core/lib/common/menu'; import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; @@ -7,19 +7,41 @@ import { ElectronCommands, } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution'; import { MainMenuManager } from '../../../common/main-menu-manager'; +import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; +import { FrontendApplication } from '@theia/core/lib/browser'; @injectable() export class ElectronMenuContribution extends TheiaElectronMenuContribution implements MainMenuManager { + @inject(FrontendApplicationStateService) + private readonly appStateService: FrontendApplicationStateService; + + private appReady = false; + private updateWhenReady = false; + + override onStart(app: FrontendApplication): void { + super.onStart(app); + this.appStateService.reachedState('ready').then(() => { + this.appReady = true; + if (this.updateWhenReady) { + this.update(); + } + }); + } + protected override hideTopPanel(): void { // NOOP // We reuse the `div` for the Arduino toolbar. } update(): void { - (this as any).setMenu(); + if (this.appReady) { + (this as any).setMenu(); + } else { + this.updateWhenReady = true; + } } override registerCommands(registry: CommandRegistry): void { diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-module.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-module.ts index 1e3b86e60..49bba615e 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-module.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-module.ts @@ -16,7 +16,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(ElectronMenuContribution).toSelf().inSingletonScope(); bind(MainMenuManager).toService(ElectronMenuContribution); rebind(TheiaElectronMenuContribution).to(ElectronMenuContribution); - bind(ElectronMainMenuFactory).toSelf().inRequestScope(); + bind(ElectronMainMenuFactory).toSelf().inSingletonScope(); rebind(TheiaElectronMainMenuFactory).toService(ElectronMainMenuFactory); bind(ElectronWindowService).toSelf().inSingletonScope(); rebind(WindowService).toService(ElectronWindowService); diff --git a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts index 67a6212c4..009045a1a 100644 --- a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts +++ b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts @@ -42,6 +42,12 @@ const WORKSPACES = 'workspaces'; const APP_STARTED_WITH_NOSPLASH = typeof process !== 'undefined' && process.argv.indexOf('--nosplash') !== -1; +/** + * If the app is started with `--open-devtools` argument, the `Dev Tools` will be opened. + */ +const APP_STARTED_WITH_DEV_TOOLS = + typeof process !== 'undefined' && process.argv.indexOf('--open-devtools') !== -1; + @injectable() export class ElectronMainApplication extends TheiaElectronMainApplication { protected startup = false; @@ -243,10 +249,22 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { options: TheiaBrowserWindowOptions ): Promise { const electronWindow = await super.createWindow(options); + if (APP_STARTED_WITH_DEV_TOOLS) { + electronWindow.webContents.openDevTools({ mode: 'undocked' }); + } this.attachListenersToWindow(electronWindow); return electronWindow; } + protected override getDefaultOptions(): TheiaBrowserWindowOptions { + const options = super.getDefaultOptions(); + if (!options.webPreferences) { + options.webPreferences = {}; + } + options.webPreferences.v8CacheOptions = 'bypassHeatCheck'; // TODO: verify this. VS Code use this V8 option. + return options; + } + private attachListenersToWindow(electronWindow: BrowserWindow) { electronWindow.webContents.on( 'new-window', From 7ccb92b2c4a7fdedc99a843d4ee0cabcfbce3c8c Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 13:42:27 +0200 Subject: [PATCH 21/45] do not parse the CLI log JSON, use as is. Signed-off-by: Akos Kitta --- .../src/node/arduino-daemon-impl.ts | 3 +- arduino-ide-extension/src/node/daemon-log.ts | 153 ------------------ 2 files changed, 1 insertion(+), 155 deletions(-) delete mode 100644 arduino-ide-extension/src/node/daemon-log.ts diff --git a/arduino-ide-extension/src/node/arduino-daemon-impl.ts b/arduino-ide-extension/src/node/arduino-daemon-impl.ts index f3995fd1d..19569440b 100644 --- a/arduino-ide-extension/src/node/arduino-daemon-impl.ts +++ b/arduino-ide-extension/src/node/arduino-daemon-impl.ts @@ -13,7 +13,6 @@ import { environment } from '@theia/application-package/lib/environment'; 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 { DaemonLog } from './daemon-log'; import { CLI_CONFIG } from './cli-config'; import { getExecPath, spawnCommand } from './exec-util'; @@ -256,7 +255,7 @@ export class ArduinoDaemonImpl } protected onData(message: string): void { - DaemonLog.log(this.logger, message); + this.logger.info(message); } protected onError(error: any): void { diff --git a/arduino-ide-extension/src/node/daemon-log.ts b/arduino-ide-extension/src/node/daemon-log.ts deleted file mode 100644 index f87a61425..000000000 --- a/arduino-ide-extension/src/node/daemon-log.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { ILogger, LogLevel } from '@theia/core/lib/common/logger'; - -export interface DaemonLog { - readonly time: string; - readonly level: DaemonLog.Level; - readonly msg: string; -} - -export namespace DaemonLog { - export interface Url { - readonly Scheme: string; - readonly Host: string; - readonly Path: string; - } - - export namespace Url { - export function is(arg: any | undefined): arg is Url { - return ( - !!arg && - typeof arg.Scheme === 'string' && - typeof arg.Host === 'string' && - typeof arg.Path === 'string' - ); - } - - export function toString(url: Url): string { - const { Scheme, Host, Path } = url; - return `${Scheme}://${Host}${Path}`; - } - } - - export interface System { - readonly os: string; - // readonly Resource: Resource; - } - - export namespace System { - export function toString(system: System): string { - return `OS: ${system.os}`; - } - } - - export interface Tool { - readonly version: string; - readonly systems: System[]; - } - - export namespace Tool { - export function is(arg: any | undefined): arg is Tool { - return !!arg && typeof arg.version === 'string' && 'systems' in arg; - } - - export function toString(tool: Tool): string { - const { version, systems } = tool; - return `Version: ${version}${ - !!systems - ? ` Systems: [${tool.systems.map(System.toString).join(', ')}]` - : '' - }`; - } - } - - export type Level = 'trace' | 'debug' | 'info' | 'warning' | 'error'; - - export function is(arg: any | undefined): arg is DaemonLog { - return ( - !!arg && - typeof arg.time === 'string' && - typeof arg.level === 'string' && - typeof arg.msg === 'string' - ); - } - - export function toLogLevel(log: DaemonLog): LogLevel { - const { level } = log; - switch (level) { - case 'trace': - return LogLevel.TRACE; - case 'debug': - return LogLevel.DEBUG; - case 'info': - return LogLevel.INFO; - case 'warning': - return LogLevel.WARN; - case 'error': - return LogLevel.ERROR; - default: - return LogLevel.INFO; - } - } - - export function log(logger: ILogger, logMessages: string): void { - const parsed = parse(logMessages); - for (const log of parsed) { - const logLevel = toLogLevel(log); - const message = toMessage(log, { omitLogLevel: true }); - logger.log(logLevel, message); - } - } - - function parse(toLog: string): DaemonLog[] { - const messages = toLog.trim().split('\n'); - const result: DaemonLog[] = []; - for (let i = 0; i < messages.length; i++) { - try { - const maybeDaemonLog = JSON.parse(messages[i]); - if (DaemonLog.is(maybeDaemonLog)) { - result.push(maybeDaemonLog); - continue; - } - } catch { - /* NOOP */ - } - result.push({ - time: new Date().toString(), - level: 'info', - msg: messages[i], - }); - } - return result; - } - - export function toPrettyString(logMessages: string): string { - const parsed = parse(logMessages); - return parsed.map((log) => toMessage(log)).join('\n') + '\n'; - } - - function toMessage( - log: DaemonLog, - options: { omitLogLevel: boolean } = { omitLogLevel: false } - ): string { - const details = Object.keys(log) - .filter((key) => key !== 'msg' && key !== 'level' && key !== 'time') - .map((key) => toDetails(log, key)) - .join(', '); - const logLevel = options.omitLogLevel - ? '' - : `[${log.level.toUpperCase()}] `; - return `${logLevel}${log.msg}${!!details ? ` [${details}]` : ''}`; - } - - function toDetails(log: DaemonLog, key: string): string { - let value = (log as any)[key]; - if (DaemonLog.Url.is(value)) { - value = DaemonLog.Url.toString(value); - } else if (DaemonLog.Tool.is(value)) { - value = DaemonLog.Tool.toString(value); - } else if (typeof value === 'object') { - value = JSON.stringify(value).replace(/\"([^(\")"]+)\":/g, '$1:'); // Remove the quotes from the property keys. - } - return `${key.toLowerCase()}: ${value}`; - } -} From 67a456d29a56ae69404627ef59252ab6ccbe519d Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 15:18:48 +0200 Subject: [PATCH 22/45] fixed port for the LS. Signed-off-by: Akos Kitta --- .../src/browser/arduino-frontend-contribution.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx index 510adf913..75a5f0a4d 100644 --- a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx +++ b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx @@ -373,7 +373,7 @@ export class ArduinoFrontendContribution ): Promise { const release = await this.languageServerStartMutex.acquire(); try { - const port = this.daemon.tryGetPort(); + const port = await this.daemon.tryGetPort(); if (!port) { return; } From dc3b748f705db84dfb0d527e0bddbfd1114242ae Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 15:36:57 +0200 Subject: [PATCH 23/45] deferred contributions to start on app ready. Signed-off-by: Akos Kitta --- .../browser/contributions/board-selection.ts | 5 +- .../src/browser/contributions/contribution.ts | 26 ++++- .../src/browser/contributions/debug.ts | 94 ++++++++++--------- .../src/browser/contributions/examples.ts | 13 ++- .../browser/contributions/include-library.ts | 5 +- .../contributions/open-recent-sketch.ts | 18 ++-- .../src/browser/contributions/sketchbook.ts | 11 ++- .../browser/contributions/upload-sketch.ts | 6 +- .../src/node/arduino-ide-backend-module.ts | 5 +- .../src/node/examples-service-impl.ts | 40 +++++--- 10 files changed, 140 insertions(+), 83 deletions(-) diff --git a/arduino-ide-extension/src/browser/contributions/board-selection.ts b/arduino-ide-extension/src/browser/contributions/board-selection.ts index b1b0bb860..1f50211fb 100644 --- a/arduino-ide-extension/src/browser/contributions/board-selection.ts +++ b/arduino-ide-extension/src/browser/contributions/board-selection.ts @@ -101,7 +101,6 @@ PID: ${PID}`; } override onStart(): void { - this.updateMenus(); this.notificationCenter.onPlatformInstalled(this.updateMenus.bind(this)); this.notificationCenter.onPlatformUninstalled(this.updateMenus.bind(this)); this.boardsServiceProvider.onBoardsConfigChanged( @@ -115,6 +114,10 @@ PID: ${PID}`; ); } + override async onReady(): Promise { + this.updateMenus(); + } + protected async updateMenus(): Promise { const [installedBoards, availablePorts, config] = await Promise.all([ this.installedBoards(), diff --git a/arduino-ide-extension/src/browser/contributions/contribution.ts b/arduino-ide-extension/src/browser/contributions/contribution.ts index 8f7ff5ba7..cea483311 100644 --- a/arduino-ide-extension/src/browser/contributions/contribution.ts +++ b/arduino-ide-extension/src/browser/contributions/contribution.ts @@ -1,4 +1,9 @@ -import { inject, injectable, interfaces } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + interfaces, + postConstruct, +} from '@theia/core/shared/inversify'; import URI from '@theia/core/lib/common/uri'; import { ILogger } from '@theia/core/lib/common/logger'; import { Saveable } from '@theia/core/lib/browser/saveable'; @@ -42,6 +47,7 @@ import { Sketch, } from '../../common/protocol'; import { ArduinoPreferences } from '../arduino-preferences'; +import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; export { Command, @@ -84,15 +90,31 @@ export abstract class Contribution @inject(SettingsService) protected readonly settingsService: SettingsService; + @inject(FrontendApplicationStateService) + protected readonly appStateService: FrontendApplicationStateService; + + @postConstruct() + protected init(): void { + this.appStateService.reachedState('ready').then(() => this.onReady()); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function, unused-imports/no-unused-vars onStart(app: FrontendApplication): MaybePromise {} + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function, unused-imports/no-unused-vars registerCommands(registry: CommandRegistry): void {} + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function, unused-imports/no-unused-vars registerMenus(registry: MenuModelRegistry): void {} + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function, unused-imports/no-unused-vars registerKeybindings(registry: KeybindingRegistry): void {} + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function, unused-imports/no-unused-vars registerToolbarItems(registry: TabBarToolbarRegistry): void {} + + // eslint-disable-next-line @typescript-eslint/no-empty-function + onReady(): MaybePromise {} } @injectable() @@ -140,7 +162,7 @@ export abstract class SketchContribution extends Contribution { } export namespace Contribution { - export function configure( + export function configure( bind: interfaces.Bind, serviceIdentifier: typeof Contribution ): void { diff --git a/arduino-ide-extension/src/browser/contributions/debug.ts b/arduino-ide-extension/src/browser/contributions/debug.ts index 05121988a..692901cf5 100644 --- a/arduino-ide-extension/src/browser/contributions/debug.ts +++ b/arduino-ide-extension/src/browser/contributions/debug.ts @@ -12,7 +12,7 @@ import { SketchContribution, TabBarToolbarRegistry, } from './contribution'; -import { nls } from '@theia/core/lib/common'; +import { MaybePromise, nls } from '@theia/core/lib/common'; @injectable() export class Debug extends SketchContribution { @@ -79,52 +79,15 @@ export class Debug extends SketchContribution { : Debug.Commands.START_DEBUGGING.label }`) ); - const refreshState = async ( - board: Board | undefined = this.boardsServiceProvider.boardsConfig - .selectedBoard - ) => { - if (!board) { - this.disabledMessage = nls.localize( - 'arduino/common/noBoardSelected', - 'No board selected' - ); - return; - } - const fqbn = board.fqbn; - if (!fqbn) { - this.disabledMessage = nls.localize( - 'arduino/debug/noPlatformInstalledFor', - "Platform is not installed for '{0}'", - board.name - ); - return; - } - const details = await this.boardService.getBoardDetails({ fqbn }); - if (!details) { - this.disabledMessage = nls.localize( - 'arduino/debug/noPlatformInstalledFor', - "Platform is not installed for '{0}'", - board.name - ); - return; - } - const { debuggingSupported } = details; - if (!debuggingSupported) { - this.disabledMessage = nls.localize( - 'arduino/debug/debuggingNotSupported', - "Debugging is not supported by '{0}'", - board.name - ); - } else { - this.disabledMessage = undefined; - } - }; this.boardsServiceProvider.onBoardsConfigChanged(({ selectedBoard }) => - refreshState(selectedBoard) + this.refreshState(selectedBoard) ); - this.notificationCenter.onPlatformInstalled(() => refreshState()); - this.notificationCenter.onPlatformUninstalled(() => refreshState()); - refreshState(); + this.notificationCenter.onPlatformInstalled(() => this.refreshState()); + this.notificationCenter.onPlatformUninstalled(() => this.refreshState()); + } + + override onReady(): MaybePromise { + this.refreshState(); } override registerCommands(registry: CommandRegistry): void { @@ -140,6 +103,47 @@ export class Debug extends SketchContribution { registry.registerItem(this.debugToolbarItem); } + private async refreshState( + board: Board | undefined = this.boardsServiceProvider.boardsConfig + .selectedBoard + ): Promise { + if (!board) { + this.disabledMessage = nls.localize( + 'arduino/common/noBoardSelected', + 'No board selected' + ); + return; + } + const fqbn = board.fqbn; + if (!fqbn) { + this.disabledMessage = nls.localize( + 'arduino/debug/noPlatformInstalledFor', + "Platform is not installed for '{0}'", + board.name + ); + return; + } + const details = await this.boardService.getBoardDetails({ fqbn }); + if (!details) { + this.disabledMessage = nls.localize( + 'arduino/debug/noPlatformInstalledFor', + "Platform is not installed for '{0}'", + board.name + ); + return; + } + const { debuggingSupported } = details; + if (!debuggingSupported) { + this.disabledMessage = nls.localize( + 'arduino/debug/debuggingNotSupported', + "Debugging is not supported by '{0}'", + board.name + ); + } else { + this.disabledMessage = undefined; + } + } + protected async startDebug( board: Board | undefined = this.boardsServiceProvider.boardsConfig .selectedBoard diff --git a/arduino-ide-extension/src/browser/contributions/examples.ts b/arduino-ide-extension/src/browser/contributions/examples.ts index 8ce379e4d..17368feab 100644 --- a/arduino-ide-extension/src/browser/contributions/examples.ts +++ b/arduino-ide-extension/src/browser/contributions/examples.ts @@ -1,5 +1,5 @@ import * as PQueue from 'p-queue'; -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { inject, injectable } from '@theia/core/shared/inversify'; import { CommandHandler } from '@theia/core/lib/common/command'; import { MenuPath, @@ -43,8 +43,8 @@ export abstract class Examples extends SketchContribution { protected readonly toDispose = new DisposableCollection(); - @postConstruct() - init(): void { + protected override init(): void { + super.init(); this.boardsServiceClient.onBoardsConfigChanged(({ selectedBoard }) => this.handleBoardChanged(selectedBoard) ); @@ -161,7 +161,7 @@ export abstract class Examples extends SketchContribution { @injectable() export class BuiltInExamples extends Examples { - override onStart(): void { + override async onReady(): Promise { this.register(); // no `await` } @@ -202,11 +202,14 @@ export class LibraryExamples extends Examples { protected readonly queue = new PQueue({ autoStart: true, concurrency: 1 }); override onStart(): void { - this.register(); // no `await` this.notificationCenter.onLibraryInstalled(() => this.register()); this.notificationCenter.onLibraryUninstalled(() => this.register()); } + override async onReady(): Promise { + this.register(); // no `await` + } + protected override handleBoardChanged(board: Board | undefined): void { this.register(board); } diff --git a/arduino-ide-extension/src/browser/contributions/include-library.ts b/arduino-ide-extension/src/browser/contributions/include-library.ts index 3f1c35baf..4b31965ae 100644 --- a/arduino-ide-extension/src/browser/contributions/include-library.ts +++ b/arduino-ide-extension/src/browser/contributions/include-library.ts @@ -45,7 +45,6 @@ export class IncludeLibrary extends SketchContribution { protected readonly toDispose = new DisposableCollection(); override onStart(): void { - this.updateMenuActions(); this.boardsServiceClient.onBoardsConfigChanged(() => this.updateMenuActions() ); @@ -55,6 +54,10 @@ export class IncludeLibrary extends SketchContribution { ); } + override async onReady(): Promise { + this.updateMenuActions(); + } + override registerMenus(registry: MenuModelRegistry): void { // `Include Library` submenu const includeLibMenuPath = [ diff --git a/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts b/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts index f3ee7b644..dfedf5d8c 100644 --- a/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/open-recent-sketch.ts @@ -36,14 +36,15 @@ export class OpenRecentSketch extends SketchContribution { protected toDisposeBeforeRegister = new Map(); override onStart(): void { - const refreshMenu = (sketches: Sketch[]) => { - this.register(sketches); - this.mainMenuManager.update(); - }; this.notificationCenter.onRecentSketchesChanged(({ sketches }) => - refreshMenu(sketches) + this.refreshMenu(sketches) ); - this.sketchService.recentlyOpenedSketches().then(refreshMenu); + } + + override async onReady(): Promise { + this.sketchService + .recentlyOpenedSketches() + .then((sketches) => this.refreshMenu(sketches)); } override registerMenus(registry: MenuModelRegistry): void { @@ -54,6 +55,11 @@ export class OpenRecentSketch extends SketchContribution { ); } + private refreshMenu(sketches: Sketch[]): void { + this.register(sketches); + this.mainMenuManager.update(); + } + protected register(sketches: Sketch[]): void { const order = 0; for (const sketch of sketches) { diff --git a/arduino-ide-extension/src/browser/contributions/sketchbook.ts b/arduino-ide-extension/src/browser/contributions/sketchbook.ts index 676eba169..80dc99065 100644 --- a/arduino-ide-extension/src/browser/contributions/sketchbook.ts +++ b/arduino-ide-extension/src/browser/contributions/sketchbook.ts @@ -24,10 +24,6 @@ export class Sketchbook extends Examples { protected readonly notificationCenter: NotificationCenter; override onStart(): void { - this.sketchService.getSketches({}).then((container) => { - this.register(container); - this.mainMenuManager.update(); - }); this.sketchServiceClient.onSketchbookDidChange(() => { this.sketchService.getSketches({}).then((container) => { this.register(container); @@ -36,6 +32,13 @@ export class Sketchbook extends Examples { }); } + override async onReady(): Promise { + this.sketchService.getSketches({}).then((container) => { + this.register(container); + this.mainMenuManager.update(); + }); + } + override registerMenus(registry: MenuModelRegistry): void { registry.registerSubmenu( ArduinoMenus.FILE__SKETCHBOOK_SUBMENU, diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index eb58c264b..7c8cae2b4 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -1,4 +1,4 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { inject, injectable } from '@theia/core/shared/inversify'; import { Emitter } from '@theia/core/lib/common/event'; import { BoardUserField, CoreService } from '../../common/protocol'; import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus'; @@ -47,8 +47,8 @@ export class UploadSketch extends SketchContribution { protected readonly menuActionsDisposables = new DisposableCollection(); - @postConstruct() - protected init(): void { + protected override init(): void { + super.init(); this.boardsServiceClientImpl.onBoardsConfigChanged(async () => { const userFields = await this.boardsServiceClientImpl.selectedBoardUserFields(); diff --git a/arduino-ide-extension/src/node/arduino-ide-backend-module.ts b/arduino-ide-extension/src/node/arduino-ide-backend-module.ts index 23ae3a083..6b39f8fb0 100644 --- a/arduino-ide-extension/src/node/arduino-ide-backend-module.ts +++ b/arduino-ide-extension/src/node/arduino-ide-backend-module.ts @@ -58,7 +58,7 @@ import { FileSystemExt, FileSystemExtPath, } from '../common/protocol/filesystem-ext'; -import { ExamplesServiceImpl } from './examples-service-impl'; +import { BuiltInExamplesServiceImpl, ExamplesServiceImpl } from './examples-service-impl'; import { ExamplesService, ExamplesServicePath, @@ -124,6 +124,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { ) .inSingletonScope(); + // Built-in examples are not board specific, so it is possible to have one shared instance. + bind(BuiltInExamplesServiceImpl).toSelf().inSingletonScope(); + // Examples service. One per backend, each connected FE gets a proxy. bind(ConnectionContainerModule).toConstantValue( ConnectionContainerModule.create(({ bind, bindBackendService }) => { diff --git a/arduino-ide-extension/src/node/examples-service-impl.ts b/arduino-ide-extension/src/node/examples-service-impl.ts index 3f8e92dfb..7b1f0f1b0 100644 --- a/arduino-ide-extension/src/node/examples-service-impl.ts +++ b/arduino-ide-extension/src/node/examples-service-impl.ts @@ -61,17 +61,8 @@ namespace BuiltInSketchContainer { } @injectable() -export class ExamplesServiceImpl implements ExamplesService { - @inject(SketchesServiceImpl) - protected readonly sketchesService: SketchesServiceImpl; - - @inject(LibraryService) - protected readonly libraryService: LibraryService; - - @inject(ConfigServiceImpl) - protected readonly configService: ConfigServiceImpl; - - protected _all: SketchContainer[] | undefined; +export class BuiltInExamplesServiceImpl { + protected _builtIns: SketchContainer[] | undefined; @postConstruct() protected init(): void { @@ -79,8 +70,8 @@ export class ExamplesServiceImpl implements ExamplesService { } async builtIns(): Promise { - if (this._all) { - return this._all; + if (this._builtIns) { + return this._builtIns; } const examplesRootPath = join(__dirname, '..', '..', 'Examples'); const examplesRootUri = FileUri.create(examplesRootPath); @@ -89,10 +80,29 @@ export class ExamplesServiceImpl implements ExamplesService { { encoding: 'utf8' } ); const examples: BuiltInSketchContainer[] = JSON.parse(rawJson); - this._all = examples.map((container) => + this._builtIns = examples.map((container) => BuiltInSketchContainer.toSketchContainer(container, examplesRootUri) ); - return this._all; + return this._builtIns; + } +} + +@injectable() +export class ExamplesServiceImpl implements ExamplesService { + @inject(SketchesServiceImpl) + protected readonly sketchesService: SketchesServiceImpl; + + @inject(LibraryService) + protected readonly libraryService: LibraryService; + + @inject(ConfigServiceImpl) + protected readonly configService: ConfigServiceImpl; + + @inject(BuiltInExamplesServiceImpl) + private readonly builtInExamplesService: BuiltInExamplesServiceImpl; + + builtIns(): Promise { + return this.builtInExamplesService.builtIns(); } // TODO: decide whether it makes sense to cache them. Keys should be: `fqbn` + version of containing core/library. From ab163a52bd4872fa0cf89b04e3b8e7f0322b4ffb Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 15:50:57 +0200 Subject: [PATCH 24/45] disabled "trick" for deferring menu update. Signed-off-by: Akos Kitta --- .../boards/boards-data-menu-updater.ts | 12 +++++++++- .../browser/contributions/board-selection.ts | 16 ++++++-------- .../theia/core/electron-menu-contribution.ts | 22 +++++++++---------- .../src/node/arduino-daemon-impl.ts | 2 +- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-data-menu-updater.ts b/arduino-ide-extension/src/browser/boards/boards-data-menu-updater.ts index a3f2ec208..5f1c42e51 100644 --- a/arduino-ide-extension/src/browser/boards/boards-data-menu-updater.ts +++ b/arduino-ide-extension/src/browser/boards/boards-data-menu-updater.ts @@ -13,6 +13,7 @@ import { BoardsDataStore } from './boards-data-store'; import { MainMenuManager } from '../../common/main-menu-manager'; import { ArduinoMenus, unregisterSubmenu } from '../menu/arduino-menus'; import { nls } from '@theia/core/lib/common'; +import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; @injectable() export class BoardsDataMenuUpdater implements FrontendApplicationContribution { @@ -31,11 +32,20 @@ export class BoardsDataMenuUpdater implements FrontendApplicationContribution { @inject(BoardsServiceProvider) protected readonly boardsServiceClient: BoardsServiceProvider; + @inject(FrontendApplicationStateService) + private readonly appStateService: FrontendApplicationStateService; + protected readonly queue = new PQueue({ autoStart: true, concurrency: 1 }); protected readonly toDisposeOnBoardChange = new DisposableCollection(); async onStart(): Promise { - this.updateMenuActions(this.boardsServiceClient.boardsConfig.selectedBoard); + this.appStateService + .reachedState('ready') + .then(() => + this.updateMenuActions( + this.boardsServiceClient.boardsConfig.selectedBoard + ) + ); this.boardsDataStore.onChanged(() => this.updateMenuActions( this.boardsServiceClient.boardsConfig.selectedBoard diff --git a/arduino-ide-extension/src/browser/contributions/board-selection.ts b/arduino-ide-extension/src/browser/contributions/board-selection.ts index 1f50211fb..16b025662 100644 --- a/arduino-ide-extension/src/browser/contributions/board-selection.ts +++ b/arduino-ide-extension/src/browser/contributions/board-selection.ts @@ -101,16 +101,14 @@ PID: ${PID}`; } override onStart(): void { - this.notificationCenter.onPlatformInstalled(this.updateMenus.bind(this)); - this.notificationCenter.onPlatformUninstalled(this.updateMenus.bind(this)); - this.boardsServiceProvider.onBoardsConfigChanged( - this.updateMenus.bind(this) + this.notificationCenter.onPlatformInstalled(() => this.updateMenus()); + this.notificationCenter.onPlatformUninstalled(() => this.updateMenus()); + this.boardsServiceProvider.onBoardsConfigChanged(() => this.updateMenus()); + this.boardsServiceProvider.onAvailableBoardsChanged(() => + this.updateMenus() ); - this.boardsServiceProvider.onAvailableBoardsChanged( - this.updateMenus.bind(this) - ); - this.boardsServiceProvider.onAvailablePortsChanged( - this.updateMenus.bind(this) + this.boardsServiceProvider.onAvailablePortsChanged(() => + this.updateMenus() ); } diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts index 4aa1cb462..a698fff51 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts @@ -18,16 +18,16 @@ export class ElectronMenuContribution @inject(FrontendApplicationStateService) private readonly appStateService: FrontendApplicationStateService; - private appReady = false; - private updateWhenReady = false; + // private appReady = false; + // private updateWhenReady = false; override onStart(app: FrontendApplication): void { super.onStart(app); this.appStateService.reachedState('ready').then(() => { - this.appReady = true; - if (this.updateWhenReady) { - this.update(); - } + // this.appReady = true; + // if (this.updateWhenReady) { + // this.update(); + // } }); } @@ -37,11 +37,11 @@ export class ElectronMenuContribution } update(): void { - if (this.appReady) { - (this as any).setMenu(); - } else { - this.updateWhenReady = true; - } + (this as any).setMenu(); + // if (this.appReady) { + // } else { + // this.updateWhenReady = true; + // } } override registerCommands(registry: CommandRegistry): void { diff --git a/arduino-ide-extension/src/node/arduino-daemon-impl.ts b/arduino-ide-extension/src/node/arduino-daemon-impl.ts index 19569440b..e53d6afe3 100644 --- a/arduino-ide-extension/src/node/arduino-daemon-impl.ts +++ b/arduino-ide-extension/src/node/arduino-daemon-impl.ts @@ -41,7 +41,7 @@ export class ArduinoDaemonImpl // Backend application lifecycle. onStart(): void { - this.startDaemon(); + this.startDaemon(); // no await } // Daemon API From 469159e813fd82804a4b00b54ad3f17747d9d483 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 16:08:05 +0200 Subject: [PATCH 25/45] updated translation files. Signed-off-by: Akos Kitta --- i18n/en.json | 1351 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1347 insertions(+), 4 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index ccda42fcf..fbed0c51d 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1,4 +1,104 @@ { + "April": "April", + "AprilShort": "Apr", + "August": "August", + "AugustShort": "Aug", + "December": "December", + "DecemberShort": "Dec", + "EditorFontZoomIn.label": "Editor Font Zoom In", + "EditorFontZoomOut.label": "Editor Font Zoom Out", + "EditorFontZoomReset.label": "Editor Font Zoom Reset", + "Error": "Error", + "February": "February", + "FebruaryShort": "Feb", + "Friday": "Friday", + "FridayShort": "Fri", + "Hint": "Hint", + "InPlaceReplaceAction.next.label": "Replace with Next Value", + "InPlaceReplaceAction.previous.label": "Replace with Previous Value", + "Info": "Info", + "January": "January", + "JanuaryShort": "Jan", + "July": "July", + "JulyShort": "Jul", + "June": "June", + "JuneShort": "Jun", + "March": "March", + "MarchShort": "Mar", + "May": "May", + "MayShort": "May", + "Monday": "Monday", + "MondayShort": "Mon", + "November": "November", + "NovemberShort": "Nov", + "October": "October", + "OctoberShort": "Oct", + "Saturday": "Saturday", + "SaturdayShort": "Sat", + "September": "September", + "SeptemberShort": "Sep", + "Sunday": "Sunday", + "SundayShort": "Sun", + "Thursday": "Thursday", + "ThursdayShort": "Thu", + "Tuesday": "Tuesday", + "TuesdayShort": "Tue", + "Warning": "Warning", + "Wednesday": "Wednesday", + "WednesdayShort": "Wed", + "accept.insert": "Insert", + "accept.replace": "Replace", + "acceptInlineSuggestion": "Accept", + "acceptSuggestionOnCommitCharacter": "Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`;`) can be a commit character that accepts a suggestion and types that character.", + "acceptSuggestionOnEnter": "Controls whether suggestions should be accepted on `Enter`, in addition to `Tab`. Helps to avoid ambiguity between inserting new lines or accepting suggestions.", + "acceptSuggestionOnEnterSmart": "Only accept a suggestion with `Enter` when it makes a textual change.", + "accessibilityHelpMessage": "Press Alt+F1 for Accessibility Options.", + "accessibilityOffAriaLabel": "The editor is not accessible at this time. Press {0} for options.", + "accessibilityPageSize": "Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 500. Warning: this has a performance implication for numbers larger than the default.", + "accessibilitySupport": "Controls whether the editor should run in a mode where it is optimized for screen readers. Setting to on will disable word wrapping.", + "accessibilitySupport.auto": "The editor will use platform APIs to detect when a Screen Reader is attached.", + "accessibilitySupport.off": "The editor will never be optimized for usage with a Screen Reader.", + "accessibilitySupport.on": "The editor will be permanently optimized for usage with a Screen Reader. Word wrapping will be disabled.", + "action.inlineSuggest.showNext": "Show Next Inline Suggestion", + "action.inlineSuggest.showPrevious": "Show Previous Inline Suggestion", + "action.inlineSuggest.trigger": "Trigger Inline Suggestion", + "action.showContextMenu.label": "Show Editor Context Menu", + "action.unicodeHighlight.disableHighlightingInComments": "Disable highlighting of characters in comments", + "action.unicodeHighlight.disableHighlightingInStrings": "Disable highlighting of characters in strings", + "action.unicodeHighlight.disableHighlightingOfAmbiguousCharacters": "Disable highlighting of ambiguous characters", + "action.unicodeHighlight.disableHighlightingOfInvisibleCharacters": "Disable highlighting of invisible characters", + "action.unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters": "Disable highlighting of non basic ASCII characters", + "action.unicodeHighlight.showExcludeOptions": "Show Exclude Options", + "actions.clipboard.copyLabel": "Copy", + "actions.clipboard.copyWithSyntaxHighlightingLabel": "Copy With Syntax Highlighting", + "actions.clipboard.cutLabel": "Cut", + "actions.clipboard.pasteLabel": "Paste", + "actions.find.isRegexOverride": "Overrides \"Use Regular Expression\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", + "actions.find.matchCaseOverride": "Overrides \"Math Case\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", + "actions.find.preserveCaseOverride": "Overrides \"Preserve Case\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", + "actions.find.wholeWordOverride": "Overrides \"Match Whole Word\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", + "actions.goToDecl.label": "Go to Definition", + "actions.goToDeclToSide.label": "Open Definition to the Side", + "actions.goToDeclaration.label": "Go to Declaration", + "actions.goToImplementation.label": "Go to Implementations", + "actions.goToTypeDefinition.label": "Go to Type Definition", + "actions.peekDecl.label": "Peek Declaration", + "actions.peekImplementation.label": "Peek Implementations", + "actions.peekTypeDefinition.label": "Peek Type Definition", + "actions.previewDecl.label": "Peek Definition", + "activeContrastBorder": "An extra border around active elements to separate them from others for greater contrast.", + "activeLinkForeground": "Color of active links.", + "addSelectionToNextFindMatch": "Add Selection To Next Find Match", + "addSelectionToPreviousFindMatch": "Add Selection To Previous Find Match", + "alertErrorMessage": "Error: {0}", + "alertInfoMessage": "Info: {0}", + "alertWarningMessage": "Warning: {0}", + "alternativeDeclarationCommand": "Alternative command id that is being executed when the result of 'Go to Declaration' is the current location.", + "alternativeDefinitionCommand": "Alternative command id that is being executed when the result of 'Go to Definition' is the current location.", + "alternativeImplementationCommand": "Alternative command id that is being executed when the result of 'Go to Implementation' is the current location.", + "alternativeReferenceCommand": "Alternative command id that is being executed when the result of 'Go to Reference' is the current location.", + "alternativeTypeDefinitionCommand": "Alternative command id that is being executed when the result of 'Go to Type Definition' is the current location.", + "applyCodeActionFailed": "An unknown error occurred while applying the code action", "arduino": { "about": { "detail": "Version: {0}\nDate: {1}{2}\nCLI Version: {3}{4} [{5}]\n\n{6}", @@ -316,36 +416,1279 @@ "upload": "Upload" } }, + "args.schema.apply": "Controls when the returned actions are applied.", + "args.schema.apply.first": "Always apply the first returned code action.", + "args.schema.apply.ifSingle": "Apply the first returned code action if it is the only one.", + "args.schema.apply.never": "Do not apply the returned code actions.", + "args.schema.kind": "Kind of the code action to run.", + "args.schema.preferred": "Controls if only preferred code actions should be returned.", + "aria": "Successfully renamed '{0}' to '{1}'. Summary: {2}", + "aria.alert.snippet": "Accepting '{0}' made {1} additional edits", + "ariaCurrenttSuggestionReadDetails": "{0}, docs: {1}", + "ariaSearchNoResult": "{0} found for '{1}'", + "ariaSearchNoResultEmpty": "{0} found", + "ariaSearchNoResultWithLineNum": "{0} found for '{1}', at {2}", + "ariaSearchNoResultWithLineNumNoCurrentMatch": "{0} found for '{1}'", + "autoClosingBrackets": "Controls whether the editor should automatically close brackets after the user adds an opening bracket.", + "autoClosingDelete": "Controls whether the editor should remove adjacent closing quotes or brackets when deleting.", + "autoClosingOvertype": "Controls whether the editor should type over closing quotes or brackets.", + "autoClosingQuotes": "Controls whether the editor should automatically close quotes after the user adds an opening quote.", + "autoFix.label": "Auto Fix...", + "autoIndent": "Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.", + "autoSurround": "Controls whether the editor should automatically surround selections when typing quotes or brackets.", + "auto_off": "The editor is configured to never be optimized for usage with a Screen Reader, which is not the case at this time.", + "auto_on": "The editor is configured to be optimized for usage with a Screen Reader.", + "badgeBackground": "Badge background color. Badges are small information labels, e.g. for search results count.", + "badgeForeground": "Badge foreground color. Badges are small information labels, e.g. for search results count.", + "blankLine": "blank", + "bracketPairColorization.enabled": "Controls whether bracket pair colorization is enabled or not. Use 'workbench.colorCustomizations' to override the bracket highlight colors.", + "breadcrumbsBackground": "Background color of breadcrumb items.", + "breadcrumbsFocusForeground": "Color of focused breadcrumb items.", + "breadcrumbsSelectedBackground": "Background color of breadcrumb item picker.", + "breadcrumbsSelectedForegound": "Color of selected breadcrumb items.", + "bulkEditServiceSummary": "Made {0} edits in {1} files", + "buttonBackground": "Button background color.", + "buttonBorder": "Button border color.", + "buttonForeground": "Button foreground color.", + "buttonHoverBackground": "Button background color when hovering.", + "buttonSecondaryBackground": "Secondary button background color.", + "buttonSecondaryForeground": "Secondary button foreground color.", + "buttonSecondaryHoverBackground": "Secondary button background color when hovering.", + "cancel": "Cancel", + "caret": "Color of the editor cursor.", + "caret.moveLeft": "Move Selected Text Left", + "caret.moveRight": "Move Selected Text Right", + "caseDescription": "Match Case", + "change": "{0} of {1} problem", + "changeAll.label": "Change All Occurrences", + "changeConfigToOnMac": "To configure the editor to be optimized for usage with a Screen Reader press Command+E now.", + "changeConfigToOnWinLinux": "To configure the editor to be optimized for usage with a Screen Reader press Control+E now.", + "chartsBlue": "The blue color used in chart visualizations.", + "chartsForeground": "The foreground color used in charts.", + "chartsGreen": "The green color used in chart visualizations.", + "chartsLines": "The color used for horizontal lines in charts.", + "chartsOrange": "The orange color used in chart visualizations.", + "chartsPurple": "The purple color used in chart visualizations.", + "chartsRed": "The red color used in chart visualizations.", + "chartsYellow": "The yellow color used in chart visualizations.", + "checkbox.background": "Background color of checkbox widget.", + "checkbox.border": "Border color of checkbox widget.", + "checkbox.foreground": "Foreground color of checkbox widget.", + "checkingForQuickFixes": "Checking for quick fixes...", "cloud": { "GoToCloud": "GO TO CLOUD" }, + "codeAction": "Show Code Actions", + "codeActionWithKb": "Show Code Actions ({0})", + "codeActions": "Enables the code action lightbulb in the editor.", + "codeLens": "Controls whether the editor shows CodeLens.", + "codeLensFontFamily": "Controls the font family for CodeLens.", + "codeLensFontSize": "Controls the font size in pixels for CodeLens. When set to `0`, 90% of `#editor.fontSize#` is used.", + "colorDecorators": "Controls whether the editor should render the inline color decorators and color picker.", + "columnSelection": "Enable that the selection with the mouse and keys is doing column selection.", + "comment.block": "Toggle Block Comment", + "comment.line": "Toggle Line Comment", + "comment.line.add": "Add Line Comment", + "comment.line.remove": "Remove Line Comment", + "comments.ignoreEmptyLines": "Controls if empty lines should be ignored with toggle, add or remove actions for line comments.", + "comments.insertSpace": "Controls whether a space character is inserted when commenting.", + "config.property.duplicate": "Cannot register '{0}'. This property is already registered.", + "config.property.empty": "Cannot register an empty property", + "config.property.languageDefault": "Cannot register '{0}'. This matches property pattern '\\[.*\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.", + "configuredTabSize": "Configured Tab Size", + "confirmDifferentSource": "Would you like to undo '{0}'?", + "confirmDifferentSource.no": "No", + "confirmDifferentSource.yes": "Yes", + "confirmWorkspace": "Would you like to undo '{0}' across all files?", + "contrastBorder": "An extra border around elements to separate them from others for greater contrast.", + "copy as": "Copy As", + "copyWithSyntaxHighlighting": "Controls whether syntax highlighting should be copied into the clipboard.", + "ctrlEnter.keybindingChanged": "Ctrl+Enter now inserts line break instead of replacing all. You can modify the keybinding for editor.action.replaceAll to override this behavior.", + "cursor.redo": "Cursor Redo", + "cursor.undo": "Cursor Undo", + "cursorAdded": "Cursor added: {0}", + "cursorBlinking": "Control the cursor animation style.", + "cursorSmoothCaretAnimation": "Controls whether the smooth caret animation should be enabled.", + "cursorStyle": "Controls the cursor style.", + "cursorSurroundingLines": "Controls the minimal number of visible leading and trailing lines surrounding the cursor. Known as 'scrollOff' or 'scrollOffset' in some other editors.", + "cursorSurroundingLinesStyle": "Controls when `cursorSurroundingLines` should be enforced.", + "cursorSurroundingLinesStyle.all": "`cursorSurroundingLines` is enforced always.", + "cursorSurroundingLinesStyle.default": "`cursorSurroundingLines` is enforced only when triggered via the keyboard or API.", + "cursorWidth": "Controls the width of the cursor when `#editor.cursorStyle#` is set to `line`.", + "cursors.maximum": "The number of cursors has been limited to {0}.", + "cursorsAdded": "Cursors added: {0}", + "debugLinuxConfiguration": "Linux specific launch configuration attributes.", + "debugName": "Name of configuration; appears in the launch configuration drop down menu.", + "debugOSXConfiguration": "OS X specific launch configuration attributes.", + "debugPostDebugTask": "Task to run after debug session ends.", + "debugPrelaunchTask": "Task to run before debug session starts.", + "debugRequest": "Request type of configuration. Can be \"launch\" or \"attach\".", + "debugServer": "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode", + "debugType": "Type of configuration.", + "debugTypeNotRecognised": "The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled.", + "debugWindowsConfiguration": "Windows specific launch configuration attributes.", + "decl.generic.noResults": "No declaration found", + "decl.noResultWord": "No declaration found for '{0}'", + "decl.title": "Declarations", + "def.title": "Definitions", + "defaultLabel": "input", + "defaultLanguageConfiguration.description": "Configure settings to be overridden for {0} language.", + "defaultLanguageConfigurationOverrides.title": "Default Language Configuration Overrides", + "definitionLinkOpensInPeek": "Controls whether the Go to Definition mouse gesture always opens the peek widget.", + "deleteInsideWord": "Delete Word", + "deleteLine": "- {0} original line {1}", + "deprecated": "This setting is deprecated, please use separate settings like 'editor.suggest.showKeywords' or 'editor.suggest.showSnippets' instead.", + "deprecatedEditorActiveLineNumber": "Id is deprecated. Use 'editorLineNumber.activeForeground' instead.", + "deprecatedVariables": "'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead.", + "descriptionForeground": "Foreground color for description text providing additional information, for example for a label.", + "detail.less": "show more", + "detail.more": "show less", + "details.close": "Close", + "detectIndentation": "Detect Indentation from Content", + "diff.clipboard.copyChangedLineContent.label": "Copy changed line ({0})", + "diff.clipboard.copyChangedLinesContent.label": "Copy changed lines", + "diff.clipboard.copyChangedLinesContent.single.label": "Copy changed line", + "diff.clipboard.copyDeletedLineContent.label": "Copy deleted line ({0})", + "diff.clipboard.copyDeletedLinesContent.label": "Copy deleted lines", + "diff.clipboard.copyDeletedLinesContent.single.label": "Copy deleted line", + "diff.inline.revertChange.label": "Revert this change", + "diff.tooLarge": "Cannot compare files because one file is too large.", + "diffDiagonalFill": "Color of the diff editor's diagonal fill. The diagonal fill is used in side-by-side diff views.", + "diffEditorBorder": "Border color between the two text editors.", + "diffEditorInserted": "Background color for text that got inserted. The color must not be opaque so as not to hide underlying decorations.", + "diffEditorInsertedLineGutter": "Background color for the margin where lines got inserted.", + "diffEditorInsertedLines": "Background color for lines that got inserted. The color must not be opaque so as not to hide underlying decorations.", + "diffEditorInsertedOutline": "Outline color for the text that got inserted.", + "diffEditorOverviewInserted": "Diff overview ruler foreground for inserted content.", + "diffEditorOverviewRemoved": "Diff overview ruler foreground for removed content.", + "diffEditorRemoved": "Background color for text that got removed. The color must not be opaque so as not to hide underlying decorations.", + "diffEditorRemovedLineGutter": "Background color for the margin where lines got removed.", + "diffEditorRemovedLines": "Background color for lines that got removed. The color must not be opaque so as not to hide underlying decorations.", + "diffEditorRemovedOutline": "Outline color for text that got removed.", + "diffInsertIcon": "Line decoration for inserts in the diff editor.", + "diffRemoveIcon": "Line decoration for removals in the diff editor.", + "diffReviewCloseIcon": "Icon for 'Close' in diff review.", + "diffReviewInsertIcon": "Icon for 'Insert' in diff review.", + "diffReviewRemoveIcon": "Icon for 'Remove' in diff review.", + "dragAndDrop": "Controls whether the editor should allow moving selections via drag and drop.", + "dropdownBackground": "Dropdown background.", + "dropdownBorder": "Dropdown border.", + "dropdownForeground": "Dropdown foreground.", + "dropdownListBackground": "Dropdown list background.", + "duplicateSelection": "Duplicate Selection", + "edit": "Typing", + "editableDiffEditor": " in a pane of a diff editor.", + "editableEditor": " in a code editor", + "editor": "editor", + "editor.action.autoFix.noneMessage": "No auto fixes available", + "editor.action.codeAction.noneMessage": "No code actions available", + "editor.action.codeAction.noneMessage.kind": "No code actions for '{0}' available", + "editor.action.codeAction.noneMessage.preferred": "No preferred code actions available", + "editor.action.codeAction.noneMessage.preferred.kind": "No preferred code actions for '{0}' available", + "editor.action.diffReview.next": "Go to Next Difference", + "editor.action.diffReview.prev": "Go to Previous Difference", + "editor.action.organize.noneMessage": "No organize imports action available", + "editor.action.quickFix.noneMessage": "No code actions available", + "editor.action.refactor.noneMessage": "No refactorings available", + "editor.action.refactor.noneMessage.kind": "No refactorings for '{0}' available", + "editor.action.refactor.noneMessage.preferred": "No preferred refactorings available", + "editor.action.refactor.noneMessage.preferred.kind": "No preferred refactorings for '{0}' available", + "editor.action.source.noneMessage": "No source actions available", + "editor.action.source.noneMessage.kind": "No source actions for '{0}' available", + "editor.action.source.noneMessage.preferred": "No preferred source actions available", + "editor.action.source.noneMessage.preferred.kind": "No preferred source actions for '{0}' available", + "editor.autoClosingBrackets.beforeWhitespace": "Autoclose brackets only when the cursor is to the left of whitespace.", + "editor.autoClosingBrackets.languageDefined": "Use language configurations to determine when to autoclose brackets.", + "editor.autoClosingDelete.auto": "Remove adjacent closing quotes or brackets only if they were automatically inserted.", + "editor.autoClosingOvertype.auto": "Type over closing quotes or brackets only if they were automatically inserted.", + "editor.autoClosingQuotes.beforeWhitespace": "Autoclose quotes only when the cursor is to the left of whitespace.", + "editor.autoClosingQuotes.languageDefined": "Use language configurations to determine when to autoclose quotes.", + "editor.autoIndent.advanced": "The editor will keep the current line's indentation, honor language defined brackets and invoke special onEnterRules defined by languages.", + "editor.autoIndent.brackets": "The editor will keep the current line's indentation and honor language defined brackets.", + "editor.autoIndent.full": "The editor will keep the current line's indentation, honor language defined brackets, invoke special onEnterRules defined by languages, and honor indentationRules defined by languages.", + "editor.autoIndent.keep": "The editor will keep the current line's indentation.", + "editor.autoIndent.none": "The editor will not insert indentation automatically.", + "editor.autoSurround.brackets": "Surround with brackets but not quotes.", + "editor.autoSurround.languageDefined": "Use language configurations to determine when to automatically surround selections.", + "editor.autoSurround.quotes": "Surround with quotes but not brackets.", + "editor.editor.gotoLocation.multipleDeclarations": "Controls the behavior the 'Go to Declaration'-command when multiple target locations exist.", + "editor.editor.gotoLocation.multipleDefinitions": "Controls the behavior the 'Go to Definition'-command when multiple target locations exist.", + "editor.editor.gotoLocation.multipleImplemenattions": "Controls the behavior the 'Go to Implementations'-command when multiple target locations exist.", + "editor.editor.gotoLocation.multipleReferences": "Controls the behavior the 'Go to References'-command when multiple target locations exist.", + "editor.editor.gotoLocation.multipleTypeDefinitions": "Controls the behavior the 'Go to Type Definition'-command when multiple target locations exist.", + "editor.find.autoFindInSelection.always": "Always turn on Find in Selection automatically.", + "editor.find.autoFindInSelection.multiline": "Turn on Find in Selection automatically when multiple lines of content are selected.", + "editor.find.autoFindInSelection.never": "Never turn on Find in Selection automatically (default).", + "editor.find.seedSearchStringFromSelection.always": "Always seed search string from the editor selection, including word at cursor position.", + "editor.find.seedSearchStringFromSelection.never": "Never seed search string from the editor selection.", + "editor.find.seedSearchStringFromSelection.selection": "Only seed search string from the editor selection.", + "editor.gotoLocation.multiple.deprecated": "This setting is deprecated, please use separate settings like 'editor.editor.gotoLocation.multipleDefinitions' or 'editor.editor.gotoLocation.multipleImplementations' instead.", + "editor.gotoLocation.multiple.goto": "Go to the primary result and enable peek-less navigation to others", + "editor.gotoLocation.multiple.gotoAndPeek": "Go to the primary result and show a peek view", + "editor.gotoLocation.multiple.peek": "Show peek view of the results (default)", + "editor.guides.bracketPairs": "Controls whether bracket pair guides are enabled or not.", + "editor.guides.bracketPairs.active": "Enables bracket pair guides only for the active bracket pair.", + "editor.guides.bracketPairs.false": "Disables bracket pair guides.", + "editor.guides.bracketPairs.true": "Enables bracket pair guides.", + "editor.guides.bracketPairsHorizontal": "Controls whether horizontal bracket pair guides are enabled or not.", + "editor.guides.bracketPairsHorizontal.active": "Enables horizontal guides only for the active bracket pair.", + "editor.guides.bracketPairsHorizontal.false": "Disables horizontal bracket pair guides.", + "editor.guides.bracketPairsHorizontal.true": "Enables horizontal guides as addition to vertical bracket pair guides.", + "editor.guides.highlightActiveBracketPair": "Controls whether the editor should highlight the active bracket pair.", + "editor.guides.highlightActiveIndentation": "Controls whether the editor should highlight the active indent guide.", + "editor.guides.indentation": "Controls whether the editor should render indent guides.", + "editor.readonly": "Cannot edit in read-only editor", + "editor.reindentlines": "Reindent Lines", + "editor.reindentselectedlines": "Reindent Selected Lines", + "editor.suggest.showClasss": "When enabled IntelliSense shows `class`-suggestions.", + "editor.suggest.showColors": "When enabled IntelliSense shows `color`-suggestions.", + "editor.suggest.showConstants": "When enabled IntelliSense shows `constant`-suggestions.", + "editor.suggest.showConstructors": "When enabled IntelliSense shows `constructor`-suggestions.", + "editor.suggest.showCustomcolors": "When enabled IntelliSense shows `customcolor`-suggestions.", + "editor.suggest.showDeprecated": "When enabled IntelliSense shows `deprecated`-suggestions.", + "editor.suggest.showEnumMembers": "When enabled IntelliSense shows `enumMember`-suggestions.", + "editor.suggest.showEnums": "When enabled IntelliSense shows `enum`-suggestions.", + "editor.suggest.showEvents": "When enabled IntelliSense shows `event`-suggestions.", + "editor.suggest.showFields": "When enabled IntelliSense shows `field`-suggestions.", + "editor.suggest.showFiles": "When enabled IntelliSense shows `file`-suggestions.", + "editor.suggest.showFolders": "When enabled IntelliSense shows `folder`-suggestions.", + "editor.suggest.showFunctions": "When enabled IntelliSense shows `function`-suggestions.", + "editor.suggest.showInterfaces": "When enabled IntelliSense shows `interface`-suggestions.", + "editor.suggest.showIssues": "When enabled IntelliSense shows `issues`-suggestions.", + "editor.suggest.showKeywords": "When enabled IntelliSense shows `keyword`-suggestions.", + "editor.suggest.showMethods": "When enabled IntelliSense shows `method`-suggestions.", + "editor.suggest.showModules": "When enabled IntelliSense shows `module`-suggestions.", + "editor.suggest.showOperators": "When enabled IntelliSense shows `operator`-suggestions.", + "editor.suggest.showPropertys": "When enabled IntelliSense shows `property`-suggestions.", + "editor.suggest.showReferences": "When enabled IntelliSense shows `reference`-suggestions.", + "editor.suggest.showSnippets": "When enabled IntelliSense shows `snippet`-suggestions.", + "editor.suggest.showStructs": "When enabled IntelliSense shows `struct`-suggestions.", + "editor.suggest.showTexts": "When enabled IntelliSense shows `text`-suggestions.", + "editor.suggest.showTypeParameters": "When enabled IntelliSense shows `typeParameter`-suggestions.", + "editor.suggest.showUnits": "When enabled IntelliSense shows `unit`-suggestions.", + "editor.suggest.showUsers": "When enabled IntelliSense shows `user`-suggestions.", + "editor.suggest.showValues": "When enabled IntelliSense shows `value`-suggestions.", + "editor.suggest.showVariables": "When enabled IntelliSense shows `variable`-suggestions.", + "editor.transformToLowercase": "Transform to Lowercase", + "editor.transformToSnakecase": "Transform to Snake Case", + "editor.transformToTitlecase": "Transform to Title Case", + "editor.transformToUppercase": "Transform to Uppercase", + "editor.transpose": "Transpose characters around the cursor", + "editorActiveIndentGuide": "Color of the active editor indentation guides.", + "editorActiveLineNumber": "Color of editor active line number", + "editorBackground": "Editor background color.", + "editorBracketHighlightForeground1": "Foreground color of brackets (1). Requires enabling bracket pair colorization.", + "editorBracketHighlightForeground2": "Foreground color of brackets (2). Requires enabling bracket pair colorization.", + "editorBracketHighlightForeground3": "Foreground color of brackets (3). Requires enabling bracket pair colorization.", + "editorBracketHighlightForeground4": "Foreground color of brackets (4). Requires enabling bracket pair colorization.", + "editorBracketHighlightForeground5": "Foreground color of brackets (5). Requires enabling bracket pair colorization.", + "editorBracketHighlightForeground6": "Foreground color of brackets (6). Requires enabling bracket pair colorization.", + "editorBracketHighlightUnexpectedBracketForeground": "Foreground color of unexpected brackets.", + "editorBracketMatchBackground": "Background color behind matching brackets", + "editorBracketMatchBorder": "Color for matching brackets boxes", + "editorBracketPairGuide.activeBackground1": "Background color of active bracket pair guides (1). Requires enabling bracket pair guides.", + "editorBracketPairGuide.activeBackground2": "Background color of active bracket pair guides (2). Requires enabling bracket pair guides.", + "editorBracketPairGuide.activeBackground3": "Background color of active bracket pair guides (3). Requires enabling bracket pair guides.", + "editorBracketPairGuide.activeBackground4": "Background color of active bracket pair guides (4). Requires enabling bracket pair guides.", + "editorBracketPairGuide.activeBackground5": "Background color of active bracket pair guides (5). Requires enabling bracket pair guides.", + "editorBracketPairGuide.activeBackground6": "Background color of active bracket pair guides (6). Requires enabling bracket pair guides.", + "editorBracketPairGuide.background1": "Background color of inactive bracket pair guides (1). Requires enabling bracket pair guides.", + "editorBracketPairGuide.background2": "Background color of inactive bracket pair guides (2). Requires enabling bracket pair guides.", + "editorBracketPairGuide.background3": "Background color of inactive bracket pair guides (3). Requires enabling bracket pair guides.", + "editorBracketPairGuide.background4": "Background color of inactive bracket pair guides (4). Requires enabling bracket pair guides.", + "editorBracketPairGuide.background5": "Background color of inactive bracket pair guides (5). Requires enabling bracket pair guides.", + "editorBracketPairGuide.background6": "Background color of inactive bracket pair guides (6). Requires enabling bracket pair guides.", + "editorCodeLensForeground": "Foreground color of editor CodeLens", + "editorColumnSelection": "Whether `editor.columnSelection` is enabled", + "editorConfigurationTitle": "Editor", + "editorCursorBackground": "The background color of the editor cursor. Allows customizing the color of a character overlapped by a block cursor.", + "editorError.background": "Background color of error text in the editor. The color must not be opaque so as not to hide underlying decorations.", + "editorError.foreground": "Foreground color of error squigglies in the editor.", + "editorFindMatch": "Color of the current search match.", + "editorFindMatchBorder": "Border color of the current search match.", + "editorFocus": "Whether the editor or an editor widget has focus (e.g. focus is in the find widget)", + "editorForeground": "Editor default foreground color.", + "editorGhostTextBackground": "Background color of the ghost text in the editor.", + "editorGhostTextBorder": "Border color of ghost text in the editor.", + "editorGhostTextForeground": "Foreground color of the ghost text in the editor.", + "editorGutter": "Background color of the editor gutter. The gutter contains the glyph margins and the line numbers.", + "editorGutter.foldingControlForeground": "Color of the folding control in the editor gutter.", + "editorHasCodeActionsProvider": "Whether the editor has a code actions provider", + "editorHasCodeLensProvider": "Whether the editor has a code lens provider", + "editorHasCompletionItemProvider": "Whether the editor has a completion item provider", + "editorHasDeclarationProvider": "Whether the editor has a declaration provider", + "editorHasDefinitionProvider": "Whether the editor has a definition provider", + "editorHasDocumentFormattingProvider": "Whether the editor has a document formatting provider", + "editorHasDocumentHighlightProvider": "Whether the editor has a document highlight provider", + "editorHasDocumentSelectionFormattingProvider": "Whether the editor has a document selection formatting provider", + "editorHasDocumentSymbolProvider": "Whether the editor has a document symbol provider", + "editorHasHoverProvider": "Whether the editor has a hover provider", + "editorHasImplementationProvider": "Whether the editor has an implementation provider", + "editorHasInlayHintsProvider": "Whether the editor has an inline hints provider", + "editorHasMultipleDocumentFormattingProvider": "Whether the editor has multiple document formatting providers", + "editorHasMultipleDocumentSelectionFormattingProvider": "Whether the editor has multiple document selection formatting providers", + "editorHasMultipleSelections": "Whether the editor has multiple selections", + "editorHasReferenceProvider": "Whether the editor has a reference provider", + "editorHasRenameProvider": "Whether the editor has a rename provider", + "editorHasSelection": "Whether the editor has text selected", + "editorHasSignatureHelpProvider": "Whether the editor has a signature help provider", + "editorHasTypeDefinitionProvider": "Whether the editor has a type definition provider", + "editorHint.foreground": "Foreground color of hint squigglies in the editor.", + "editorHoverVisible": "Whether the editor hover is visible", + "editorHoverWidgetHighlightForeground": "Foreground color of the active item in the parameter hint.", + "editorInactiveSelection": "Color of the selection in an inactive editor. The color must not be opaque so as not to hide underlying decorations.", + "editorIndentGuides": "Color of the editor indentation guides.", + "editorInfo.background": "Background color of info text in the editor. The color must not be opaque so as not to hide underlying decorations.", + "editorInfo.foreground": "Foreground color of info squigglies in the editor.", + "editorInlayHintBackground": "Background color of inline hints", + "editorInlayHintBackgroundParameter": "Background color of inline hints for parameters", + "editorInlayHintBackgroundTypes": "Background color of inline hints for types", + "editorInlayHintForeground": "Foreground color of inline hints", + "editorInlayHintForegroundParameter": "Foreground color of inline hints for parameters", + "editorInlayHintForegroundTypes": "Foreground color of inline hints for types", + "editorLangId": "The language identifier of the editor", + "editorLightBulbAutoFixForeground": "The color used for the lightbulb auto fix actions icon.", + "editorLightBulbForeground": "The color used for the lightbulb actions icon.", + "editorLineNumbers": "Color of editor line numbers.", + "editorLinkedEditingBackground": "Background color when the editor auto renames on type.", + "editorMarkerNavigationBackground": "Editor marker navigation widget background.", + "editorMarkerNavigationError": "Editor marker navigation widget error color.", + "editorMarkerNavigationErrorHeaderBackground": "Editor marker navigation widget error heading background.", + "editorMarkerNavigationInfo": "Editor marker navigation widget info color.", + "editorMarkerNavigationInfoHeaderBackground": "Editor marker navigation widget info heading background.", + "editorMarkerNavigationWarning": "Editor marker navigation widget warning color.", + "editorMarkerNavigationWarningBackground": "Editor marker navigation widget warning heading background.", + "editorOverviewRulerBackground": "Background color of the editor overview ruler. Only used when the minimap is enabled and placed on the right side of the editor.", + "editorOverviewRulerBorder": "Color of the overview ruler border.", + "editorReadonly": "Whether the editor is read only", + "editorRuler": "Color of the editor rulers.", + "editorSelectionBackground": "Color of the editor selection.", + "editorSelectionForeground": "Color of the selected text for high contrast.", + "editorSelectionHighlight": "Color for regions with the same content as the selection. The color must not be opaque so as not to hide underlying decorations.", + "editorSelectionHighlightBorder": "Border color for regions with the same content as the selection.", + "editorSuggestWidgetBackground": "Background color of the suggest widget.", + "editorSuggestWidgetBorder": "Border color of the suggest widget.", + "editorSuggestWidgetFocusHighlightForeground": "Color of the match highlights in the suggest widget when an item is focused.", + "editorSuggestWidgetForeground": "Foreground color of the suggest widget.", + "editorSuggestWidgetHighlightForeground": "Color of the match highlights in the suggest widget.", + "editorSuggestWidgetSelectedBackground": "Background color of the selected entry in the suggest widget.", + "editorSuggestWidgetSelectedForeground": "Foreground color of the selected entry in the suggest widget.", + "editorSuggestWidgetSelectedIconForeground": "Icon foreground color of the selected entry in the suggest widget.", + "editorSuggestWidgetStatusForeground": "Foreground color of the suggest widget status.", + "editorTabMovesFocus": "Whether `Tab` will move focus out of the editor", + "editorTextFocus": "Whether the editor text has focus (cursor is blinking)", + "editorUnicodeHighlight.border": "Border color used to highlight unicode characters.", + "editorViewAccessibleLabel": "Editor content", + "editorWarning.background": "Background color of warning text in the editor. The color must not be opaque so as not to hide underlying decorations.", + "editorWarning.foreground": "Foreground color of warning squigglies in the editor.", + "editorWhitespaces": "Color of whitespace characters in the editor.", + "editorWidgetBackground": "Background color of editor widgets, such as find/replace.", + "editorWidgetBorder": "Border color of editor widgets. The color is only used if the widget chooses to have a border and if the color is not overridden by a widget.", + "editorWidgetForeground": "Foreground color of editor widgets, such as find/replace.", + "editorWidgetResizeBorder": "Border color of the resize bar of editor widgets. The color is only used if the widget chooses to have a resize border and if the color is not overridden by a widget.", + "emergencyConfOn": "Now changing the setting `accessibilitySupport` to 'on'.", + "emptySelectionClipboard": "Controls whether copying without a selection copies the current line.", + "enablePreview": "Enable/disable the ability to preview changes before renaming", + "equalLine": "{0} original line {1} modified line {2}", + "error.defaultMessage": "An unknown error occurred. Please consult the log for more details.", + "error.moreErrors": "{0} ({1} errors in total)", + "errorBorder": "Border color of error boxes in the editor.", + "errorForeground": "Overall foreground color for error messages. This color is only used if not overridden by a component.", + "expandLineSelection": "Expand Line Selection", + "fastScrollSensitivity": "Scrolling speed multiplier when pressing `Alt`.", + "find.addExtraSpaceOnTop": "Controls whether the Find Widget should add extra lines on top of the editor. When true, you can scroll beyond the first line when the Find Widget is visible.", + "find.autoFindInSelection": "Controls the condition for turning on Find in Selection automatically.", + "find.cursorMoveOnType": "Controls whether the cursor should jump to find matches while typing.", + "find.globalFindClipboard": "Controls whether the Find Widget should read or modify the shared find clipboard on macOS.", + "find.loop": "Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found.", + "find.seedSearchStringFromSelection": "Controls whether the search string in the Find Widget is seeded from the editor selection.", + "findCollapsedIcon": "Icon to indicate that the editor find widget is collapsed.", + "findExpandedIcon": "Icon to indicate that the editor find widget is expanded.", + "findMatchHighlight": "Color of the other search matches. The color must not be opaque so as not to hide underlying decorations.", + "findMatchHighlightBorder": "Border color of the other search matches.", + "findNextMatchAction": "Find Next", + "findNextMatchIcon": "Icon for 'Find Next' in the editor find widget.", + "findPreviousMatchAction": "Find Previous", + "findPreviousMatchIcon": "Icon for 'Find Previous' in the editor find widget.", + "findRangeHighlight": "Color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations.", + "findRangeHighlightBorder": "Border color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations.", + "findReplaceAllIcon": "Icon for 'Replace All' in the editor find widget.", + "findReplaceIcon": "Icon for 'Replace' in the editor find widget.", + "findSelectionIcon": "Icon for 'Find in Selection' in the editor find widget.", + "first.chord": "({0}) was pressed. Waiting for second key of chord...", + "fixAll.label": "Fix All", + "fixAll.noneMessage": "No fix all action available", + "focusBorder": "Overall border color for focused elements. This color is only used if not overridden by a component.", + "foldAction.label": "Fold", + "foldAllAction.label": "Fold All", + "foldAllBlockComments.label": "Fold All Block Comments", + "foldAllExcept.label": "Fold All Regions Except Selected", + "foldAllMarkerRegions.label": "Fold All Regions", + "foldBackgroundBackground": "Background color behind folded ranges. The color must not be opaque so as not to hide underlying decorations.", + "foldLevelAction.label": "Fold Level {0}", + "foldRecursivelyAction.label": "Fold Recursively", + "folding": "Controls whether the editor has code folding enabled.", + "foldingHighlight": "Controls whether the editor should highlight folded ranges.", + "foldingImportsByDefault": "Controls whether the editor automatically collapses import ranges.", + "foldingMaximumRegions": "The maximum number of foldable regions. Increasing this value may result in the editor becoming less responsive when the current source has a large number of foldable regions.", + "foldingStrategy": "Controls the strategy for computing folding ranges.", + "foldingStrategy.auto": "Use a language-specific folding strategy if available, else the indentation-based one.", + "foldingStrategy.indentation": "Use the indentation-based folding strategy.", + "fontFamily": "Controls the font family.", + "fontFeatureSettings": "Explicit 'font-feature-settings' CSS property. A boolean can be passed instead if one only needs to turn on/off ligatures.", + "fontLigatures": "Enables/Disables font ligatures ('calt' and 'liga' font features). Change this to a string for fine-grained control of the 'font-feature-settings' CSS property.", + "fontLigaturesGeneral": "Configures font ligatures or font features. Can be either a boolean to enable/disable ligatures or a string for the value of the CSS 'font-feature-settings' property.", + "fontSize": "Controls the font size in pixels.", + "fontWeight": "Controls the font weight. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000.", + "fontWeightErrorMessage": "Only \"normal\" and \"bold\" keywords or numbers between 1 and 1000 are allowed.", + "forceRetokenize": "Developer: Force Retokenize", + "foreground": "Overall foreground color. This color is only used if not overridden by a component.", + "formatDocument.label": "Format Document", + "formatOnPaste": "Controls whether the editor should automatically format the pasted content. A formatter must be available and the formatter should be able to format a range in a document.", + "formatOnType": "Controls whether the editor should automatically format the line after typing.", + "formatSelection.label": "Format Selection", + "generic.noResult": "No results for '{0}'", + "generic.noResults": "No definition found", + "generic.title": "Locations", + "glyphMargin": "Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.", + "goToImplementation.generic.noResults": "No implementation found", + "goToImplementation.noResultWord": "No implementation found for '{0}'", + "goToReferences.label": "Go to References", + "goToTypeDefinition.generic.noResults": "No type definition found", + "goToTypeDefinition.noResultWord": "No type definition found for '{0}'", + "gotoLineActionLabel": "Go to Line/Column...", + "gotoNextFold.label": "Go to Next Folding Range", + "gotoParentFold.label": "Go to Parent Fold", + "gotoPreviousFold.label": "Go to Previous Folding Range", + "helpQuickAccess": "Show all Quick Access Providers", + "hideCursorInOverviewRuler": "Controls whether the cursor should be hidden in the overview ruler.", + "highlight": "List/Tree foreground color of the match highlights when searching inside the list/tree.", + "hint": "{0}, hint", + "hint11": "Made 1 formatting edit on line {0}", + "hint1n": "Made 1 formatting edit between lines {0} and {1}", + "hintBorder": "Border color of hint boxes in the editor.", + "hintn1": "Made {0} formatting edits on line {1}", + "hintnn": "Made {0} formatting edits between lines {1} and {2}", + "hover.above": "Prefer showing hovers above the line, if there's space.", + "hover.delay": "Controls the delay in milliseconds after which the hover is shown.", + "hover.enabled": "Controls whether the hover is shown.", + "hover.sticky": "Controls whether the hover should remain visible when mouse is moved over it.", + "hoverBackground": "Background color of the editor hover.", + "hoverBorder": "Border color of the editor hover.", + "hoverForeground": "Foreground color of the editor hover.", + "hoverHighlight": "Highlight below the word for which a hover is shown. The color must not be opaque so as not to hide underlying decorations.", + "iconForeground": "The default color for icons in the workbench.", + "ignoreTrimWhitespace": "When enabled, the diff editor ignores changes in leading or trailing whitespace.", + "impl.title": "Implementations", + "inCompositeEditor": "Whether the editor is part of a larger editor (e.g. notebooks)", + "inDiffEditor": "Whether the context is a diff editor", + "inReferenceSearchEditor": "Whether the current code editor is embedded inside peek", + "indentUsingSpaces": "Indent Using Spaces", + "indentUsingTabs": "Indent Using Tabs", + "indentationToSpaces": "Convert Indentation to Spaces", + "indentationToTabs": "Convert Indentation to Tabs", + "infoBorder": "Border color of info boxes in the editor.", + "inlayHints.enable": "Enables the inlay hints in the editor.", + "inlayHints.fontFamily": "Controls font family of inlay hints in the editor. When set to empty, the `#editor.fontFamily#` is used.", + "inlayHints.fontSize": "Controls font size of inlay hints in the editor. A default of 90% of `#editor.fontSize#` is used when the configured value is less than `5` or greater than the editor font size.", + "inlineSuggest.enabled": "Controls whether to automatically show inline suggestions in the editor.", + "inlineSuggestionFollows": "Suggestion:", + "inlineSuggestionHasIndentation": "Whether the inline suggestion starts with whitespace", + "inlineSuggestionHasIndentationLessThanTabSize": "Whether the inline suggestion starts with whitespace that is less than what would be inserted by tab", + "inlineSuggestionVisible": "Whether an inline suggestion is visible", + "inputBoxActiveOptionBorder": "Border color of activated options in input fields.", + "inputBoxBackground": "Input box background.", + "inputBoxBorder": "Input box border.", + "inputBoxForeground": "Input box foreground.", + "inputOption.activeBackground": "Background hover color of options in input fields.", + "inputOption.activeForeground": "Foreground color of activated options in input fields.", + "inputOption.hoverBackground": "Background color of activated options in input fields.", + "inputPlaceholderForeground": "Input box foreground color for placeholder text.", + "inputValidationErrorBackground": "Input validation background color for error severity.", + "inputValidationErrorBorder": "Input validation border color for error severity.", + "inputValidationErrorForeground": "Input validation foreground color for error severity.", + "inputValidationInfoBackground": "Input validation background color for information severity.", + "inputValidationInfoBorder": "Input validation border color for information severity.", + "inputValidationInfoForeground": "Input validation foreground color for information severity.", + "inputValidationWarningBackground": "Input validation background color for warning severity.", + "inputValidationWarningBorder": "Input validation border color for warning severity.", + "inputValidationWarningForeground": "Input validation foreground color for warning severity.", + "insertLine": "+ {0} modified line {1}", + "insertSpaces": "Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.", + "inspectTokens": "Developer: Inspect Tokens", + "internalConsoleOptions": "Controls when the internal debug console should open.", + "invalid.url": "Failed to open this link because it is not well-formed: {0}", + "invalidItemForeground": "List/Tree foreground color for invalid items, for example an unresolved root in explorer.", + "keybindingLabelBackground": "Keybinding label background color. The keybinding label is used to represent a keyboard shortcut.", + "keybindingLabelBorder": "Keybinding label border color. The keybinding label is used to represent a keyboard shortcut.", + "keybindingLabelBottomBorder": "Keybinding label border bottom color. The keybinding label is used to represent a keyboard shortcut.", + "keybindingLabelForeground": "Keybinding label foreground color. The keybinding label is used to represent a keyboard shortcut.", + "label": "Renaming '{0}'", + "label.close": "Close", + "label.closeButton": "Close", + "label.desc": "{0}, {1}", + "label.detail": "{0}{1}", + "label.find": "Find", + "label.full": "{0}{1}, {2}", + "label.generic": "Go to Any Symbol", + "label.matchesLocation": "{0} of {1}", + "label.nextMatchButton": "Next Match", + "label.noResults": "No results", + "label.preserveCaseCheckbox": "Preserve Case", + "label.previousMatchButton": "Previous Match", + "label.replace": "Replace", + "label.replaceAllButton": "Replace All", + "label.replaceButton": "Replace", + "label.toggleReplaceButton": "Toggle Replace", + "label.toggleSelectionFind": "Find in Selection", + "labelLoading": "Loading...", + "largeFileOptimizations": "Special handling for large files to disable certain memory intensive features.", + "letterSpacing": "Controls the letter spacing in pixels.", + "lineHeight": "Controls the line height. \n - Use 0 to automatically compute the line height from the font size.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values.", + "lineHighlight": "Background color for the highlight of line at the cursor position.", + "lineHighlightBorderBox": "Background color for the border around the line at the cursor position.", + "lineNumbers": "Controls the display of line numbers.", + "lineNumbers.interval": "Line numbers are rendered every 10 lines.", + "lineNumbers.off": "Line numbers are not rendered.", + "lineNumbers.on": "Line numbers are rendered as absolute number.", + "lineNumbers.relative": "Line numbers are rendered as distance in lines to cursor position.", + "lines.copyDown": "Copy Line Down", + "lines.copyUp": "Copy Line Up", + "lines.delete": "Delete Line", + "lines.deleteAllLeft": "Delete All Left", + "lines.deleteAllRight": "Delete All Right", + "lines.deleteDuplicates": "Delete Duplicate Lines", + "lines.indent": "Indent Line", + "lines.insertAfter": "Insert Line Below", + "lines.insertBefore": "Insert Line Above", + "lines.joinLines": "Join Lines", + "lines.moveDown": "Move Line Down", + "lines.moveUp": "Move Line Up", + "lines.outdent": "Outdent Line", + "lines.sortAscending": "Sort Lines Ascending", + "lines.sortDescending": "Sort Lines Descending", + "lines.trimTrailingWhitespace": "Trim Trailing Whitespace", + "linkedEditing": "Controls whether the editor has linked editing enabled. Depending on the language, related symbols, e.g. HTML tags, are updated while editing.", + "linkedEditing.label": "Start Linked Editing", + "links": "Controls whether the editor should detect links and make them clickable.", + "links.navigate.executeCmd": "Execute command", + "links.navigate.follow": "Follow link", + "links.navigate.kb.alt": "alt + click", + "links.navigate.kb.alt.mac": "option + click", + "links.navigate.kb.meta": "ctrl + click", + "links.navigate.kb.meta.mac": "cmd + click", + "listActiveSelectionBackground": "List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", + "listActiveSelectionForeground": "List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", + "listActiveSelectionIconForeground": "List/Tree icon foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", + "listDeemphasizedForeground": "List/Tree foreground color for items that are deemphasized. ", + "listDropBackground": "List/Tree drag and drop background when moving items around using the mouse.", + "listErrorForeground": "Foreground color of list items containing errors.", + "listFilterMatchHighlight": "Background color of the filtered match.", + "listFilterMatchHighlightBorder": "Border color of the filtered match.", + "listFilterWidgetBackground": "Background color of the type filter widget in lists and trees.", + "listFilterWidgetNoMatchesOutline": "Outline color of the type filter widget in lists and trees, when there are no matches.", + "listFilterWidgetOutline": "Outline color of the type filter widget in lists and trees.", + "listFocusBackground": "List/Tree background color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", + "listFocusForeground": "List/Tree foreground color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", + "listFocusHighlightForeground": "List/Tree foreground color of the match highlights on actively focused items when searching inside the list/tree.", + "listFocusOutline": "List/Tree outline color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", + "listHoverBackground": "List/Tree background when hovering over items using the mouse.", + "listHoverForeground": "List/Tree foreground when hovering over items using the mouse.", + "listInactiveFocusBackground": "List/Tree background color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", + "listInactiveFocusOutline": "List/Tree outline color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", + "listInactiveSelectionBackground": "List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", + "listInactiveSelectionForeground": "List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", + "listInactiveSelectionIconForeground": "List/Tree icon foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", + "listWarningForeground": "Foreground color of list items containing warnings.", + "loading": "Loading...", + "marker aria": "{0} at {1}. ", + "markerAction.next.label": "Go to Next Problem (Error, Warning, Info)", + "markerAction.nextInFiles.label": "Go to Next Problem in Files (Error, Warning, Info)", + "markerAction.previous.label": "Go to Previous Problem (Error, Warning, Info)", + "markerAction.previousInFiles.label": "Go to Previous Problem in Files (Error, Warning, Info)", + "matchBrackets": "Highlight matching brackets.", + "maxComputationTime": "Timeout in milliseconds after which diff computation is cancelled. Use 0 for no timeout.", + "maxFileSize": "Maximum file size in MB for which to compute diffs. Use 0 for no limit.", + "maxTokenizationLineLength": "Lines above this length will not be tokenized for performance reasons", + "maximum fold ranges": "The number of foldable regions is limited to a maximum of {0}. Increase configuration option ['Folding Maximum Regions'](command:workbench.action.openSettings?[\"editor.foldingMaximumRegions\"]) to enable more.", + "menuBackground": "Background color of menu items.", + "menuBorder": "Border color of menus.", + "menuForeground": "Foreground color of menu items.", + "menuSelectionBackground": "Background color of the selected menu item in menus.", + "menuSelectionBorder": "Border color of the selected menu item in menus.", + "menuSelectionForeground": "Foreground color of the selected menu item in menus.", + "menuSeparatorBackground": "Color of a separator menu item in menus.", + "mergeBorder": "Border color on headers and the splitter in inline merge-conflicts.", + "mergeCommonContentBackground": "Common ancestor content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", + "mergeCommonHeaderBackground": "Common ancestor header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", + "mergeCurrentContentBackground": "Current content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", + "mergeCurrentHeaderBackground": "Current header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", + "mergeIncomingContentBackground": "Incoming content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", + "mergeIncomingHeaderBackground": "Incoming header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", + "messageVisible": "Whether the editor is currently showing an inline message", + "metaTitle.N": "{0} ({1})", + "minimap.enabled": "Controls whether the minimap is shown.", + "minimap.maxColumn": "Limit the width of the minimap to render at most a certain number of columns.", + "minimap.renderCharacters": "Render the actual characters on a line as opposed to color blocks.", + "minimap.scale": "Scale of content drawn in the minimap: 1, 2 or 3.", + "minimap.showSlider": "Controls when the minimap slider is shown.", + "minimap.side": "Controls the side where to render the minimap.", + "minimap.size": "Controls the size of the minimap.", + "minimap.size.fill": "The minimap will stretch or shrink as necessary to fill the height of the editor (no scrolling).", + "minimap.size.fit": "The minimap will shrink as necessary to never be larger than the editor (no scrolling).", + "minimap.size.proportional": "The minimap has the same size as the editor contents (and might scroll).", + "minimapBackground": "Minimap background color.", + "minimapError": "Minimap marker color for errors.", + "minimapFindMatchHighlight": "Minimap marker color for find matches.", + "minimapForegroundOpacity": "Opacity of foreground elements rendered in the minimap. For example, \"#000000c0\" will render the elements with 75% opacity.", + "minimapSelectionHighlight": "Minimap marker color for the editor selection.", + "minimapSelectionOccurrenceHighlight": "Minimap marker color for repeating editor selections.", + "minimapSliderActiveBackground": "Minimap slider background color when clicked on.", + "minimapSliderBackground": "Minimap slider background color.", + "minimapSliderHoverBackground": "Minimap slider background color when hovering.", + "missing.chord": "The key combination ({0}, {1}) is not a command.", + "missing.url": "Failed to open this link because its target is missing.", + "missingPreviewMessage": "no preview available", + "modesContentHover.loading": "Loading...", + "more_lines_changed": "{0} lines changed", + "mouseWheelScrollSensitivity": "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.", + "mouseWheelZoom": "Zoom the font of the editor when using mouse wheel and holding `Ctrl`.", + "moveSelectionToNextFindMatch": "Move Last Selection To Next Find Match", + "moveSelectionToPreviousFindMatch": "Move Last Selection To Previous Find Match", + "multiCursorMergeOverlapping": "Merge multiple cursors when they are overlapping.", + "multiCursorModifier.alt": "Maps to `Alt` on Windows and Linux and to `Option` on macOS.", + "multiCursorModifier.ctrlCmd": "Maps to `Control` on Windows and Linux and to `Command` on macOS.", + "multiCursorPaste": "Controls pasting when the line count of the pasted text matches the cursor count.", + "multiCursorPaste.full": "Each cursor pastes the full text.", + "multiCursorPaste.spread": "Each cursor pastes a single line of the text.", + "multiSelection": "{0} selections", + "multiSelectionRange": "{0} selections ({1} characters selected)", + "multipleResults": "Click to show {0} definitions.", + "mutlicursor.addCursorsToBottom": "Add Cursors To Bottom", + "mutlicursor.addCursorsToTop": "Add Cursors To Top", + "mutlicursor.insertAbove": "Add Cursor Above", + "mutlicursor.insertAtEndOfEachLineSelected": "Add Cursors to Line Ends", + "mutlicursor.insertBelow": "Add Cursor Below", + "nextMarkerIcon": "Icon for goto next marker.", + "nextSelectionMatchFindAction": "Find Next Selection", + "no result": "No result.", + "noQuickFixes": "No quick fixes available", + "noResultWord": "No definition found for '{0}'", + "noResults": "No results", + "noSelection": "No selection", + "no_lines_changed": "no lines changed", + "node2NotSupported": "\"node2\" is no longer supported, use \"node\" instead and set the \"protocol\" attribute to \"inspector\".", + "nodeExceptionMessage": "A system error occurred ({0})", + "nok": "Undo this File", + "occurrencesHighlight": "Controls whether the editor should highlight semantic symbol occurrences.", + "one_line_changed": "1 line changed", + "openDocMac": "Press Command+H now to open a browser window with more information related to editor accessibility.", + "openDocWinLinux": "Press Control+H now to open a browser window with more information related to editor accessibility.", + "openingDocs": "Now opening the Editor Accessibility documentation page.", + "organizeImports.label": "Organize Imports", + "outroMsg": "You can dismiss this tooltip and return to the editor by pressing Escape or Shift+Escape.", + "overrideSettings.defaultDescription": "Configure editor settings to be overridden for a language.", + "overrideSettings.errorMessage": "This setting does not support per-language configuration.", + "overviewRuleError": "Overview ruler marker color for errors.", + "overviewRuleInfo": "Overview ruler marker color for infos.", + "overviewRuleWarning": "Minimap marker color for warnings.", + "overviewRulerBorder": "Controls whether a border should be drawn around the overview ruler.", + "overviewRulerBracketMatchForeground": "Overview ruler marker color for matching brackets.", + "overviewRulerCommonContentForeground": "Common ancestor overview ruler foreground for inline merge-conflicts.", + "overviewRulerCurrentContentForeground": "Current overview ruler foreground for inline merge-conflicts.", + "overviewRulerFindMatchForeground": "Overview ruler marker color for find matches. The color must not be opaque so as not to hide underlying decorations.", + "overviewRulerIncomingContentForeground": "Incoming overview ruler foreground for inline merge-conflicts.", + "overviewRulerRangeHighlight": "Overview ruler marker color for range highlights. The color must not be opaque so as not to hide underlying decorations.", + "overviewRulerSelectionHighlightForeground": "Overview ruler marker color for selection highlights. The color must not be opaque so as not to hide underlying decorations.", + "overviewRulerWordHighlightForeground": "Overview ruler marker color for symbol highlights. The color must not be opaque so as not to hide underlying decorations.", + "overviewRulerWordHighlightStrongForeground": "Overview ruler marker color for write-access symbol highlights. The color must not be opaque so as not to hide underlying decorations.", + "padding.bottom": "Controls the amount of space between the bottom edge of the editor and the last line.", + "padding.top": "Controls the amount of space between the top edge of the editor and the first line.", + "parameterHints.cycle": "Controls whether the parameter hints menu cycles or closes when reaching the end of the list.", + "parameterHints.enabled": "Enables a pop-up that shows parameter documentation and type information as you type.", + "parameterHints.trigger.label": "Trigger Parameter Hints", + "parameterHintsNextIcon": "Icon for show next parameter hint.", + "parameterHintsPreviousIcon": "Icon for show previous parameter hint.", + "peek.submenu": "Peek", + "peekView.alternateTitle": "References", + "peekViewBorder": "Color of the peek view borders and arrow.", + "peekViewEditorBackground": "Background color of the peek view editor.", + "peekViewEditorGutterBackground": "Background color of the gutter in the peek view editor.", + "peekViewEditorMatchHighlight": "Match highlight color in the peek view editor.", + "peekViewEditorMatchHighlightBorder": "Match highlight border in the peek view editor.", + "peekViewResultsBackground": "Background color of the peek view result list.", + "peekViewResultsFileForeground": "Foreground color for file nodes in the peek view result list.", + "peekViewResultsMatchForeground": "Foreground color for line nodes in the peek view result list.", + "peekViewResultsMatchHighlight": "Match highlight color in the peek view result list.", + "peekViewResultsSelectionBackground": "Background color of the selected entry in the peek view result list.", + "peekViewResultsSelectionForeground": "Foreground color of the selected entry in the peek view result list.", + "peekViewTitleBackground": "Background color of the peek view title area.", + "peekViewTitleForeground": "Color of the peek view title.", + "peekViewTitleInfoForeground": "Color of the peek view title info.", + "peekWidgetDefaultFocus": "Controls whether to focus the inline editor or the tree in the peek widget.", + "peekWidgetDefaultFocus.editor": "Focus the editor when opening peek", + "peekWidgetDefaultFocus.tree": "Focus the tree when opening peek", + "pickerBackground": "Quick picker background color. The quick picker widget is the container for pickers like the command palette.", + "pickerForeground": "Quick picker foreground color. The quick picker widget is the container for pickers like the command palette.", + "pickerGroupBorder": "Quick picker color for grouping borders.", + "pickerGroupForeground": "Quick picker color for grouping labels.", + "pickerTitleBackground": "Quick picker title background color. The quick picker widget is the container for pickers like the command palette.", + "placeholder.find": "Find", + "placeholder.replace": "Replace", + "plainText.alias": "Plain Text", + "preferredcodeActionWithKb": "Show Code Actions. Preferred Quick Fix Available ({0})", + "previousMarkerIcon": "Icon for goto previous marker.", + "previousSelectionMatchFindAction": "Find Previous Selection", + "problems": "{0} of {1} problems", + "problemsErrorIconForeground": "The color used for the problems error icon.", + "problemsInfoIconForeground": "The color used for the problems info icon.", + "problemsWarningIconForeground": "The color used for the problems warning icon.", + "progressBarBackground": "Background color of the progress bar that can show for long running operations.", + "quick fixes": "Quick Fix...", + "quickCommandActionHelp": "Show And Run Commands", + "quickCommandActionLabel": "Command Palette", + "quickInput.list.focusBackground deprecation": "Please use quickInputList.focusBackground instead", + "quickInput.listFocusBackground": "Quick picker background color for the focused item.", + "quickInput.listFocusForeground": "Quick picker foreground color for the focused item.", + "quickInput.listFocusIconForeground": "Quick picker icon foreground color for the focused item.", + "quickOutlineActionLabel": "Go to Symbol...", + "quickOutlineByCategoryActionLabel": "Go to Symbol by Category...", + "quickSuggestions": "Controls whether suggestions should automatically show up while typing.", + "quickSuggestions.comments": "Enable quick suggestions inside comments.", + "quickSuggestions.other": "Enable quick suggestions outside of strings and comments.", + "quickSuggestions.strings": "Enable quick suggestions inside strings.", + "quickSuggestionsDelay": "Controls the delay in milliseconds after which quick suggestions will show up.", + "quickfix.trigger.label": "Quick Fix...", + "quotableLabel": "Renaming {0}", + "rangeHighlight": "Background color of highlighted ranges, like by quick open and find features. The color must not be opaque so as not to hide underlying decorations.", + "rangeHighlightBorder": "Background color of the border around highlighted ranges.", + "readMore": "Read More", + "readonlyDiffEditor": " in a read-only pane of a diff editor.", + "readonlyEditor": " in a read-only code editor", + "redo": "Redo", + "ref.title": "References", + "refactor.label": "Refactor...", + "referenceSearchVisible": "Whether reference peek is visible, like 'Peek References' or 'Peek Definition'", + "references.action.label": "Peek References", + "references.no": "No references found for '{0}'", + "references.noGeneric": "No references found", + "regexDescription": "Use Regular Expression", + "removedCursor": "Removed secondary cursors", + "rename.failed": "Rename failed to compute edits", + "rename.failedApply": "Rename failed to apply edits", + "rename.label": "Rename Symbol", + "renameOnType": "Controls whether the editor auto renames on type.", + "renameOnTypeDeprecate": "Deprecated, use `editor.linkedEditing` instead.", + "renderControlCharacters": "Controls whether the editor should render control characters.", + "renderFinalNewline": "Render last line number when the file ends with a newline.", + "renderIndicators": "Controls whether the diff editor shows +/- indicators for added/removed changes.", + "renderLineHighlight": "Controls how the editor should render the current line highlight.", + "renderLineHighlight.all": "Highlights both the gutter and the current line.", + "renderLineHighlightOnlyWhenFocus": "Controls if the editor should render the current line highlight only when the editor is focused.", + "renderWhitespace": "Controls how the editor should render whitespace characters.", + "renderWhitespace.boundary": "Render whitespace characters except for single spaces between words.", + "renderWhitespace.selection": "Render whitespace characters only on selected text.", + "renderWhitespace.trailing": "Render only trailing whitespace characters.", + "resolveRenameLocationFailed": "An unknown error occurred while resolving rename location", + "roundedSelection": "Controls whether selections should have rounded corners.", + "rulers": "Render vertical rulers after a certain number of monospace characters. Use multiple values for multiple rulers. No rulers are drawn if array is empty.", + "rulers.color": "Color of this editor ruler.", + "rulers.size": "Number of monospace characters at which this editor ruler will render.", + "sashActiveBorder": "Border color of active sashes.", + "schema.brackets": "Defines the bracket symbols that increase or decrease the indentation.", + "schema.closeBracket": "The closing bracket character or string sequence.", + "schema.colorizedBracketPairs": "Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled.", + "schema.openBracket": "The opening bracket character or string sequence.", + "scrollBeyondLastColumn": "Controls the number of extra characters beyond which the editor will scroll horizontally.", + "scrollBeyondLastLine": "Controls whether the editor will scroll beyond the last line.", + "scrollPredominantAxis": "Scroll only along the predominant axis when scrolling both vertically and horizontally at the same time. Prevents horizontal drift when scrolling vertically on a trackpad.", + "scrollbar.horizontal": "Controls the visibility of the horizontal scrollbar.", + "scrollbar.horizontal.auto": "The horizontal scrollbar will be visible only when necessary.", + "scrollbar.horizontal.fit": "The horizontal scrollbar will always be hidden.", + "scrollbar.horizontal.visible": "The horizontal scrollbar will always be visible.", + "scrollbar.horizontalScrollbarSize": "The height of the horizontal scrollbar.", + "scrollbar.scrollByPage": "Controls whether clicks scroll by page or jump to click position.", + "scrollbar.vertical": "Controls the visibility of the vertical scrollbar.", + "scrollbar.vertical.auto": "The vertical scrollbar will be visible only when necessary.", + "scrollbar.vertical.fit": "The vertical scrollbar will always be hidden.", + "scrollbar.vertical.visible": "The vertical scrollbar will always be visible.", + "scrollbar.verticalScrollbarSize": "The width of the vertical scrollbar.", + "scrollbarShadow": "Scrollbar shadow to indicate that the view is scrolled.", + "scrollbarSliderActiveBackground": "Scrollbar slider background color when clicked on.", + "scrollbarSliderBackground": "Scrollbar slider background color.", + "scrollbarSliderHoverBackground": "Scrollbar slider background color when hovering.", + "searchEditor.editorFindMatchBorder": "Border color of the Search Editor query matches.", + "searchEditor.queryMatch": "Color of the Search Editor query matches.", + "selectAll": "Select All", + "selectAllOccurrencesOfFindMatch": "Select All Occurrences of Find Match", + "selectLeadingAndTrailingWhitespace": "Whether leading and trailing whitespace should always be selected.", + "selectionBackground": "The background color of text selections in the workbench (e.g. for input fields or text areas). Note that this does not apply to selections within the editor.", + "selectionClipboard": "Controls whether the Linux primary clipboard should be supported.", + "selectionHighlight": "Controls whether the editor should highlight matches similar to the selection.", + "semanticHighlighting.configuredByTheme": "Semantic highlighting is configured by the current color theme's `semanticHighlighting` setting.", + "semanticHighlighting.enabled": "Controls whether the semanticHighlighting is shown for the languages that support it.", + "semanticHighlighting.false": "Semantic highlighting disabled for all color themes.", + "semanticHighlighting.true": "Semantic highlighting enabled for all color themes.", + "showAccessibilityHelpAction": "Show Accessibility Help", + "showDeprecated": "Controls strikethrough deprecated variables.", + "showFoldingControls": "Controls when the folding controls on the gutter are shown.", + "showFoldingControls.always": "Always show the folding controls.", + "showFoldingControls.mouseover": "Only show the folding controls when the mouse is over the gutter.", + "showNextInlineSuggestion": "Next", + "showPreviousInlineSuggestion": "Previous", + "showUnused": "Controls fading out of unused code.", + "sideBySide": "Controls whether the diff editor shows the diff side by side or inline.", + "singleSelection": "Line {0}, Column {1}", + "singleSelectionRange": "Line {0}, Column {1} ({2} selected)", + "smartSelect.expand": "Expand Selection", + "smartSelect.jumpBracket": "Go to Bracket", + "smartSelect.selectToBracket": "Select to Bracket", + "smartSelect.shrink": "Shrink Selection", + "smoothScrolling": "Controls whether the editor will scroll using an animation.", + "snippetFinalTabstopHighlightBackground": "Highlight background color of the final tabstop of a snippet.", + "snippetFinalTabstopHighlightBorder": "Highlight border color of the final tabstop of a snippet.", + "snippetSuggestions": "Controls whether snippets are shown with other suggestions and how they are sorted.", + "snippetSuggestions.bottom": "Show snippet suggestions below other suggestions.", + "snippetSuggestions.inline": "Show snippets suggestions with other suggestions.", + "snippetSuggestions.none": "Do not show snippet suggestions.", + "snippetSuggestions.top": "Show snippet suggestions on top of other suggestions.", + "snippetTabstopHighlightBackground": "Highlight background color of a snippet tabstop.", + "snippetTabstopHighlightBorder": "Highlight border color of a snippet tabstop.", + "source.label": "Source Action...", + "stablePeek": "Keep peek editors open even when double clicking their content or when hitting `Escape`.", + "stackTrace.format": "{0}: {1}", + "startFindAction": "Find", + "startFindWithArgsAction": "Find With Arguments", + "startFindWithSelectionAction": "Find With Selection", + "startReplace": "Replace", + "statusBarBackground": "Background color of the editor hover status bar.", + "stickyTabStops": "Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.", + "stickydesc": "Stick to the end even when going to longer lines", + "submenu.empty": "(empty)", + "suggest": "Suggest", + "suggest.filterGraceful": "Controls whether filtering and sorting suggestions accounts for small typos.", + "suggest.insertMode": "Controls whether words are overwritten when accepting completions. Note that this depends on extensions opting into this feature.", + "suggest.insertMode.insert": "Insert suggestion without overwriting text right of the cursor.", + "suggest.insertMode.replace": "Insert suggestion and overwrite text right of the cursor.", + "suggest.localityBonus": "Controls whether sorting favors words that appear close to the cursor.", + "suggest.maxVisibleSuggestions.dep": "This setting is deprecated. The suggest widget can now be resized.", + "suggest.preview": "Controls whether to preview the suggestion outcome in the editor.", + "suggest.reset.label": "Reset Suggest Widget Size", + "suggest.shareSuggestSelections": "Controls whether remembered suggestion selections are shared between multiple workspaces and windows (needs `#editor.suggestSelection#`).", + "suggest.showIcons": "Controls whether to show or hide icons in suggestions.", + "suggest.showInlineDetails": "Controls whether suggest details show inline with the label or only in the details widget", + "suggest.showStatusBar": "Controls the visibility of the status bar at the bottom of the suggest widget.", + "suggest.snippetsPreventQuickSuggestions": "Controls whether an active snippet prevents quick suggestions.", + "suggest.trigger.label": "Trigger Suggest", + "suggestFontSize": "Font size for the suggest widget. When set to `0`, the value of `#editor.fontSize#` is used.", + "suggestLineHeight": "Line height for the suggest widget. When set to `0`, the value of `#editor.lineHeight#` is used. The minimum value is 8.", + "suggestMoreInfoIcon": "Icon for more information in the suggest widget.", + "suggestOnTriggerCharacters": "Controls whether suggestions should automatically show up when typing trigger characters.", + "suggestSelection": "Controls how suggestions are pre-selected when showing the suggest list.", + "suggestSelection.first": "Always select the first suggestion.", + "suggestSelection.recentlyUsed": "Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log` because `log` has been completed recently.", + "suggestSelection.recentlyUsedByPrefix": "Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`.", + "suggestWidget.loading": "Loading...", + "suggestWidget.noSuggestions": "No suggestions.", + "symbolHighlight": "Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations.", + "symbolHighlightBorder": "Background color of the border around highlighted symbols.", + "tabCompletion": "Enables tab completions.", + "tabCompletion.off": "Disable tab completions.", + "tabCompletion.on": "Tab complete will insert the best matching suggestion when pressing tab.", + "tabCompletion.onlySnippets": "Tab complete snippets when their prefix match. Works best when 'quickSuggestions' aren't enabled.", + "tabFocusModeOffMsg": "Pressing Tab in the current editor will insert the tab character. Toggle this behavior by pressing {0}.", + "tabFocusModeOffMsgNoKb": "Pressing Tab in the current editor will insert the tab character. The command {0} is currently not triggerable by a keybinding.", + "tabFocusModeOnMsg": "Pressing Tab in the current editor will move focus to the next focusable element. Toggle this behavior by pressing {0}.", + "tabFocusModeOnMsgNoKb": "Pressing Tab in the current editor will move focus to the next focusable element. The command {0} is currently not triggerable by a keybinding.", + "tabSize": "The number of spaces a tab is equal to. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.", + "tableColumnsBorder": "Table border color between columns.", + "tableOddRowsBackgroundColor": "Background color for odd table rows.", + "textBlockQuoteBackground": "Background color for block quotes in text.", + "textBlockQuoteBorder": "Border color for block quotes in text.", + "textCodeBlockBackground": "Background color for code blocks in text.", + "textInputFocus": "Whether an editor or a rich text input has focus (cursor is blinking)", + "textLinkActiveForeground": "Foreground color for links in text when clicked on and on mouse hover.", + "textLinkForeground": "Foreground color for links in text.", + "textPreformatForeground": "Foreground color for preformatted text segments.", + "textSeparatorForeground": "Color for text separators.", "theia": { + "callhierarchy": { + "open": "Open Call Hierarchy" + }, "core": { "cannotConnectBackend": "Cannot connect to the backend.", "cannotConnectDaemon": "Cannot connect to the CLI daemon.", + "common": { + "closeAll": "Close All Tabs", + "closeAllTabMain": "Close All Tabs in Main Area", + "closeOtherTabMain": "Close Other Tabs in Main Area", + "closeOthers": "Close Other Tabs", + "closeRight": "Close Tabs to the Right", + "closeTab": "Close Tab", + "closeTabMain": "Close Tab in Main Area", + "collapseAllTabs": "Collapse All Side Panels", + "collapseBottomPanel": "Toggle Bottom Panel", + "collapseTab": "Collapse Side Panel", + "showNextTabGroup": "Switch to Next Tab Group", + "showNextTabInGroup": "Switch to Next Tab in Group", + "showPreviousTabGroup": "Switch to Previous Tab Group", + "showPreviousTabInGroup": "Switch to Previous Tab in Group", + "toggleMaximized": "Toggle Maximized" + }, "couldNotSave": "Could not save the sketch. Please copy your unsaved work into your favorite text editor, and restart the IDE.", "daemonOffline": "CLI Daemon Offline", - "offline": "Offline" + "file": { + "browse": "Browse" + }, + "highlightModifiedTabs": "Controls whether a top border is drawn on modified (dirty) editor tabs or not.", + "keyboard": { + "choose": "Choose Keyboard Layout", + "chooseLayout": "Choose a keyboard layout", + "current": "(current: {0})", + "currentLayout": " - current layout", + "mac": "Mac Keyboards", + "pc": "PC Keyboards", + "tryDetect": "Try to detect the keyboard layout from browser information and pressed keys." + }, + "offline": "Offline", + "quitMessage": "Any unsaved changes will not be saved.", + "quitTitle": "Are you sure you want to quit?", + "resetWorkbenchLayout": "Reset Workbench Layout", + "sashDelay": "Controls the hover feedback delay in milliseconds of the dragging area in between views/editors.", + "sashSize": "Controls the feedback area size in pixels of the dragging area in between views/editors. Set it to a larger value if needed.", + "silentNotifications": "Controls whether to suppress notification popups." }, "debug": { + "addConfigurationPlaceholder": "Select workspace root to add configuration to", + "continueAll": "Continue All", + "copyExpressionValue": "Copy Expression Value", + "debugViewLocation": "Controls the location of the debug view.", + "openBottom": "Open Bottom", + "openLeft": "Open Left", + "openRight": "Open Right", + "pauseAll": "Pause All", + "reveal": "Reveal", "start": "Start...", "startError": "There was an error starting the debug session, check the logs for more details.", + "threads": "Threads", + "toggleTracing": "Enable/disable tracing communications with debug adapters", "typeNotSupported": "The debug session type \"{0}\" is not supported." }, "editor": { + "diffEditor.maxFileSize": "Maximum file size in MB for which to compute diffs. Use 0 for no limit.", + "editor.accessibilityPageSize": "Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 500. Warning: this has a performance implication for numbers larger than the default.", + "editor.autoClosingDelete": "Controls whether the editor should remove adjacent closing quotes or brackets when deleting.", + "editor.autoClosingDelete1": "Remove adjacent closing quotes or brackets only if they were automatically inserted.", + "editor.bracketPairColorization.enabled": "Controls whether bracket pair colorization is enabled or not. Use 'workbench.colorCustomizations' to override the bracket highlight colors.", + "editor.codeLensFontSize": "Controls the font size in pixels for CodeLens. When set to `0`, 90% of `#editor.fontSize#` is used.", + "editor.find.autoFindInSelection0": "Never turn on Find in Selection automatically (default).", + "editor.find.autoFindInSelection1": "Always turn on Find in Selection automatically.", + "editor.find.seedSearchStringFromSelection0": "Never seed search string from the editor selection.", + "editor.find.seedSearchStringFromSelection1": "Always seed search string from the editor selection, including word at cursor position.", + "editor.find.seedSearchStringFromSelection2": "Only seed search string from the editor selection.", + "editor.foldingImportsByDefault": "Controls whether the editor automatically collapses import ranges.", + "editor.foldingMaximumRegions": "The maximum number of foldable regions. Increasing this value may result in the editor becoming less responsive when the current source has a large number of foldable regions.", + "editor.formatOnSaveMode.modificationsIfAvailable": "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted.", + "editor.guides.bracketPairs": "Controls whether bracket pair guides are enabled or not.", + "editor.guides.bracketPairs0": "Enables bracket pair guides.", + "editor.guides.bracketPairs1": "Enables bracket pair guides only for the active bracket pair.", + "editor.guides.bracketPairs2": "Disables bracket pair guides.", + "editor.guides.bracketPairsHorizontal": "Controls whether horizontal bracket pair guides are enabled or not.", + "editor.guides.bracketPairsHorizontal0": "Enables horizontal guides as addition to vertical bracket pair guides.", + "editor.guides.bracketPairsHorizontal1": "Enables horizontal guides only for the active bracket pair.", + "editor.guides.bracketPairsHorizontal2": "Disables horizontal bracket pair guides.", + "editor.guides.highlightActiveBracketPair": "Controls whether the editor should highlight the active bracket pair.", + "editor.hover.above": "Prefer showing hovers above the line, if there's space.", + "editor.inlayHints.enabled": "Enables the inlay hints in the editor.", + "editor.inlayHints.fontFamily": "Controls font family of inlay hints in the editor. When set to empty, the `#editor.fontFamily#` is used.", + "editor.inlayHints.fontSize": "Controls font size of inlay hints in the editor. A default of 90% of `#editor.fontSize#` is used when the configured value is less than `5` or greater than the editor font size.", + "editor.inlineSuggest.enabled": "Controls whether to automatically show inline suggestions in the editor.", + "editor.language.colorizedBracketPairs": "Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled.", + "editor.lineHeight": "Controls the line height. \n - Use 0 to automatically compute the line height from the font size.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values.", + "editor.renderLineHighlightOnlyWhenFocus": "Controls if the editor should render the current line highlight only when the editor is focused.", + "editor.renderWhitespace3": "Render only trailing whitespace characters.", + "editor.scrollbar.horizontal": "Controls the visibility of the horizontal scrollbar.", + "editor.scrollbar.horizontal0": "The horizontal scrollbar will be visible only when necessary.", + "editor.scrollbar.horizontal1": "The horizontal scrollbar will always be visible.", + "editor.scrollbar.horizontal2": "The horizontal scrollbar will always be hidden.", + "editor.scrollbar.horizontalScrollbarSize": "The height of the horizontal scrollbar.", + "editor.scrollbar.scrollByPage": "Controls whether clicks scroll by page or jump to click position.", + "editor.scrollbar.vertical": "Controls the visibility of the vertical scrollbar.", + "editor.scrollbar.vertical0": "The vertical scrollbar will be visible only when necessary.", + "editor.scrollbar.vertical1": "The vertical scrollbar will always be visible.", + "editor.scrollbar.vertical2": "The vertical scrollbar will always be hidden.", + "editor.scrollbar.verticalScrollbarSize": "The width of the vertical scrollbar.", + "editor.stickyTabStops": "Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.", + "editor.suggest.localityBonus": "Controls whether sorting favors words that appear close to the cursor.", + "editor.suggest.preview": "Controls whether to preview the suggestion outcome in the editor.", + "editor.suggest.showDeprecated": "When enabled IntelliSense shows `deprecated`-suggestions.", + "editor.unicodeHighlight.allowedCharacters": "Defines allowed characters that are not being highlighted.", + "editor.unicodeHighlight.allowedLocales": "Unicode characters that are common in allowed locales are not being highlighted.", + "editor.unicodeHighlight.ambiguousCharacters": "Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.", + "editor.unicodeHighlight.includeComments": "Controls whether characters in comments should also be subject to unicode highlighting.", + "editor.unicodeHighlight.includeStrings": "Controls whether characters in strings should also be subject to unicode highlighting.", + "editor.unicodeHighlight.invisibleCharacters": "Controls whether characters that just reserve space or have no width at all are highlighted.", + "editor.unicodeHighlight.nonBasicASCII": "Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.", + "editor.wordBasedSuggestionsMode": "Controls from which documents word based completions are computed.", + "files.autoSave": "Controls [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors that have unsaved changes.", + "files.autoSave.afterDelay": "An editor with changes is automatically saved after the configured `#files.autoSaveDelay#`.", + "files.autoSave.off": "An editor with changes is never automatically saved.", + "files.autoSave.onFocusChange": "An editor with changes is automatically saved when the editor loses focus.", + "files.autoSave.onWindowChange": "An editor with changes is automatically saved when the window loses focus.", + "formatOnSaveTimeout": "Timeout in milliseconds after which the formatting that is run on file save is cancelled.", + "persistClosedEditors": "Controls whether to persist closed editor history for the workspace across window reloads.", + "showAllEditors": "Show All Opened Editors", + "splitHorizontal": "Split Editor Horizontal", + "splitVertical": "Split Editor Vertical", "unsavedTitle": "Unsaved – {0}" }, + "file-search": { + "toggleIgnoredFiles": " (Press {0} to show/hide ignored files)" + }, + "fileSystem": { + "fileResource": { + "overWriteBody": "Do you want to overwrite the changes made to '{0}' on the file system?" + } + }, + "filesystem": { + "copyDownloadLink": "Copy Download Link", + "fileResource": { + "binaryFileQuery": "Opening it might take some time and might make the IDE unresponsive. Do you want to open '{0}' anyway?", + "binaryTitle": "The file is either binary or uses an unsupported text encoding.", + "largeFileTitle": "The file is too large ({0}).", + "overwriteTitle": "The file '{0}' has been changed on the file system." + }, + "filesExclude": "Configure glob patterns for excluding files and folders. For example, the file Explorer decides which files and folders to show or hide based on this setting.", + "maxConcurrentUploads": "Maximum number of concurrent files to upload when uploading multiple files. 0 means all files will be uploaded concurrently.", + "maxFileSizeMB": "Controls the max file size in MB which is possible to open.", + "processedOutOf": "Processed {0} out of {1}", + "uploadFiles": "Upload Files...", + "uploadedOutOf": "Uploaded {0} out of {1}" + }, + "git": { + "addSignedOff": "Add Signed-off-by", + "added": "Added", + "amendReuseMessag": "To reuse the last commit message, press 'Enter' or 'Escape' to cancel.", + "amendRewrite": "Rewrite previous commit message. Press 'Enter' to confirm or 'Escape' to cancel.", + "checkoutCreateLocalBranchWithName": "Create a new local branch with name: {0}. Press 'Enter' to confirm or 'Escape' to cancel.", + "checkoutProvideBranchName": "Please provide a branch name. ", + "checkoutSelectRef": "Select a ref to checkout or create a new local branch:", + "cloneQuickInputLabel": "Please provide a Git repository location. Press 'Enter' to confirm or 'Escape' to cancel.", + "cloneRepository": "Clone the Git repository: {0}. Press 'Enter' to confirm or 'Escape' to cancel.", + "compareWith": "Compare With...", + "compareWithBranchOrTag": "Pick a branch or tag to compare with the currently active {0} branch:", + "conflicted": "Conflicted", + "copied": "Copied", + "dirtyDiffLinesLimit": "Do not show dirty diff decorations, if editor's line count exceeds this limit.", + "dropStashMessage": "Stash successfully removed.", + "editorDecorationsEnabled": "Show git decorations in the editor.", + "fetchPickRemote": "Pick a remote to fetch from:", + "gitDecorationsColors": "Use color decoration in the navigator.", + "mergeQuickPickPlaceholder": "Pick a branch to merge into the currently active {0} branch:", + "missingUserInfo": "Make sure you configure your 'user.name' and 'user.email' in git.", + "noPreviousCommit": "No previous commit to amend", + "noRepositoriesSelected": "No repositories were selected.", + "renamed": "Renamed", + "repositoryNotInitialized": "Repository {0} is not yet initialized.", + "stashChanges": "Stash changes. Press 'Enter' to confirm or 'Escape' to cancel.", + "stashChangesWithMessage": "Stash changes with message: {0}. Press 'Enter' to confirm or 'Escape' to cancel.", + "toggleBlameAnnotations": "Toggle Blame Annotations", + "unstaged": "Unstaged" + }, + "keybinding-schema-updater": { + "deprecation": "Use `when` clause instead." + }, + "markers": { + "clearAll": "Clear All", + "tabbarDecorationsEnabled": "Show problem decorators (diagnostic markers) in the tab bars." + }, "messages": { "collapse": "Collapse", - "expand": "Expand" + "expand": "Expand", + "notificationTimeout": "Informative notifications will be hidden after this timeout.", + "toggleNotifications": "Toggle Notifications" + }, + "monaco": { + "noSymbolsMatching": "No symbols matching", + "typeToSearchForSymbols": "Type to search for symbols" + }, + "navigator": { + "autoReveal": "Auto Reveal", + "refresh": "Refresh in Explorer", + "reveal": "Reveal in Explorer", + "toggleHiddenFiles": "Toggle Hidden Files" + }, + "output": { + "clearOutputChannel": "Clear Output Channel...", + "closeOutputChannel": "Close Output Channel...", + "hiddenChannels": "Hidden Channels", + "hideOutputChannel": "Hide Output Channel...", + "maxChannelHistory": "The maximum number of entries in an output channel.", + "outputChannels": "Output Channels", + "showOutputChannel": "Show Output Channel..." + }, + "plugin-ext": { + "plugins": "Plugins", + "signInAgain": "The extension '{0}' wants you to sign in again using {1}.", + "webviewTrace": "Controls communication tracing with webviews.", + "webviewWarnIfUnsecure": "Warns users that webviews are currently deployed unsecurely." + }, + "scm": { + "amend": "Amend", + "amendHeadCommit": "HEAD Commit", + "amendLastCommit": "Amend last commit", + "changeRepository": "Change Repository...", + "history": "History", + "noRepositoryFound": "No repository found", + "unamend": "Unamend", + "unamendCommit": "Unamend commit" + }, + "search-in-workspace": { + "includeIgnoredFiles": "Include Ignored Files", + "noFolderSpecified": "You have not opened or specified a folder. Only open files are currently searched.", + "resultSubset": "This is only a subset of all results. Use a more specific search term to narrow down the result list.", + "searchOnEditorModification": "Search the active editor when modified." + }, + "task": { + "attachTask": "Attach Task...", + "clearHistory": "Clear History", + "openUserTasks": "Open User Tasks" + }, + "terminal": { + "confirmClose": "Controls whether to confirm when the window closes if there are active terminal sessions.", + "confirmCloseAlways": "Always confirm if there are terminals.", + "confirmCloseChildren": "Confirm if there are any terminals that have child processes.", + "confirmCloseNever": "Never confirm.", + "enableCopy": "Enable ctrl-c (cmd-c on macOS) to copy selected text", + "enablePaste": "Enable ctrl-v (cmd-v on macOS) to paste from clipboard", + "shellArgsLinux": "The command line arguments to use when on the Linux terminal.", + "shellArgsOsx": "The command line arguments to use when on the macOS terminal.", + "shellArgsWindows": "The command line arguments to use when on the Windows terminal.", + "shellLinux": "The path of the shell that the terminal uses on Linux (default: '{0}'}).", + "shellOsx": "The path of the shell that the terminal uses on macOS (default: '{0}'}).", + "shellWindows": "The path of the shell that the terminal uses on Windows. (default: '{0}').", + "terminate": "Terminate", + "terminateActive": "Do you want to terminate the active terminal session?", + "terminateActiveMultiple": "Do you want to terminate the {0} active terminal sessions?" + }, + "webview": { + "goToReadme": "Go To README", + "messageWarning": " The {0} endpoint's host pattern has been changed to `{1}`; changing the pattern can lead to security vulnerabilities. See `{2}` for more information." }, "workspace": { + "closeWorkspace": "Do you really want to close the workspace?", + "compareWithEachOther": "Compare with Each Other", + "confirmDeletePermanently.description": "Failed to delete \"{0}\" using the Trash. Do you want to permanently delete instead?", + "confirmDeletePermanently.solution": "You can disable the use of Trash in the preferences.", + "confirmDeletePermanently.title": "Error deleting file", "deleteCurrentSketch": "Do you want to delete the current sketch?", + "duplicate": "Duplicate", + "failApply": "Could not apply changes to new file", + "failSaveAs": "Cannot run \"{0}\" for the current widget.", "fileNewName": "Name for new file", "invalidExtension": ".{0} is not a valid extension", "invalidFilename": "Invalid filename.", "newFileName": "New name for file", - "sketchDirectoryError": "There was an error creating the sketch directory. See the log for more details. The application will probably not work as expected." + "noErasure": "Note: Nothing will be erased from disk", + "openRecentPlaceholder": "Type the name of the workspace you want to open", + "openRecentWorkspace": "Open Recent Workspace...", + "preserveWindow": "Enable opening workspaces in current window.", + "removeFolder": "Are you sure you want to remove the following folder from the workspace?", + "removeFolders": "Are you sure you want to remove the following folders from the workspace?", + "sketchDirectoryError": "There was an error creating the sketch directory. See the log for more details. The application will probably not work as expected.", + "supportMultiRootWorkspace": "Controls whether multi-root workspace support is enabled.", + "trustEmptyWindow": "Controls whether or not the empty workspace is trusted by default.", + "trustEnabled": "Controls whether or not workspace trust is enabled. If disabled, all workspaces are trusted.", + "trustPrompt": "Controls when the startup prompt to trust a workspace is shown.", + "trustRequest": "An extension requests workspace trust but the corresponding API is not yet fully supported. Do you want to trust this workspace?", + "untitled-cleanup": "There appear to be many untitled workspace files. Please check {0} and remove any unused files.", + "workspaceFolderAdded": "A workspace with multiple roots was created. Do you want to save your workspace configuration as a file?", + "workspaceFolderAddedTitle": "Folder added to Workspace" } - } + }, + "title.matchesCountLimit": "Only the first {0} results are highlighted, but all find operations work on the entire text.", + "toggle.tabMovesFocus.off": "Pressing Tab will now insert the tab character", + "toggle.tabMovesFocus.on": "Pressing Tab will now move focus to the next focusable element", + "toggleFoldAction.label": "Toggle Fold", + "toggleHighContrast": "Toggle High Contrast Theme", + "too many characters": "Tokenization is skipped for long lines for performance reasons. This can be configured via `editor.maxTokenizationLineLength`.", + "toolbarActiveBackground": "Toolbar background when holding the mouse over actions", + "toolbarHoverBackground": "Toolbar background when hovering over actions using the mouse", + "toolbarHoverOutline": "Toolbar outline when hovering over actions using the mouse", + "tooltip.explanation": "Execute command {0}", + "transposeLetters.label": "Transpose Letters", + "treeIndentGuidesStroke": "Tree stroke color for the indentation guides.", + "trimAutoWhitespace": "Remove trailing auto inserted whitespace.", + "typedef.title": "Type Definitions", + "unFoldRecursivelyAction.label": "Unfold Recursively", + "undo": "Undo", + "unfoldAction.label": "Unfold", + "unfoldAllAction.label": "Unfold All", + "unfoldAllExcept.label": "Unfold All Regions Except Selected", + "unfoldAllMarkerRegions.label": "Unfold All Regions", + "unfoldOnClickAfterEndOfLine": "Controls whether clicking on the empty content after a folded line will unfold the line.", + "unicodeHighlight.adjustSettings": "Adjust settings", + "unicodeHighlight.allowCommonCharactersInLanguage": "Allow unicode characters that are more common in the language \"{0}\".", + "unicodeHighlight.allowedCharacters": "Defines allowed characters that are not being highlighted.", + "unicodeHighlight.allowedLocales": "Unicode characters that are common in allowed locales are not being highlighted.", + "unicodeHighlight.ambiguousCharacters": "Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.", + "unicodeHighlight.characterIsAmbiguous": "The character {0} could be confused with the character {1}, which is more common in source code.", + "unicodeHighlight.characterIsInvisible": "The character {0} is invisible.", + "unicodeHighlight.characterIsNonBasicAscii": "The character {0} is not a basic ASCII character.", + "unicodeHighlight.configureUnicodeHighlightOptions": "Configure Unicode Highlight Options", + "unicodeHighlight.disableHighlightingInComments.shortLabel": "Disable Highlight In Comments", + "unicodeHighlight.disableHighlightingInStrings.shortLabel": "Disable Highlight In Strings", + "unicodeHighlight.disableHighlightingOfAmbiguousCharacters.shortLabel": "Disable Ambiguous Highlight", + "unicodeHighlight.disableHighlightingOfInvisibleCharacters.shortLabel": "Disable Invisible Highlight", + "unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters.shortLabel": "Disable Non ASCII Highlight", + "unicodeHighlight.excludeCharFromBeingHighlighted": "Exclude {0} from being highlighted", + "unicodeHighlight.excludeInvisibleCharFromBeingHighlighted": "Exclude {0} (invisible character) from being highlighted", + "unicodeHighlight.includeComments": "Controls whether characters in comments should also be subject to unicode highlighting.", + "unicodeHighlight.includeStrings": "Controls whether characters in strings should also be subject to unicode highlighting.", + "unicodeHighlight.invisibleCharacters": "Controls whether characters that just reserve space or have no width at all are highlighted.", + "unicodeHighlight.nonBasicASCII": "Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.", + "unicodeHighlighting.thisDocumentHasManyAmbiguousUnicodeCharacters": "This document contains many ambiguous unicode characters", + "unicodeHighlighting.thisDocumentHasManyInvisibleUnicodeCharacters": "This document contains many invisible unicode characters", + "unicodeHighlighting.thisDocumentHasManyNonBasicAsciiUnicodeCharacters": "This document contains many non-basic ASCII unicode characters", + "unnecessaryCodeBorder": "Border color of unnecessary (unused) source code in the editor.", + "unnecessaryCodeOpacity": "Opacity of unnecessary (unused) source code in the editor. For example, \"#000000c0\" will render the code with 75% opacity. For high contrast themes, use the 'editorUnnecessaryCode.border' theme color to underline unnecessary code instead of fading it out.", + "unusualLineTerminators": "Remove unusual line terminators that might cause problems.", + "unusualLineTerminators.auto": "Unusual line terminators are automatically removed.", + "unusualLineTerminators.detail": "The file '{0}' contains one or more unusual line terminator characters, like Line Separator (LS) or Paragraph Separator (PS).\n\nIt is recommended to remove them from the file. This can be configured via `editor.unusualLineTerminators`.", + "unusualLineTerminators.fix": "Remove Unusual Line Terminators", + "unusualLineTerminators.ignore": "Ignore", + "unusualLineTerminators.message": "Detected unusual line terminators", + "unusualLineTerminators.off": "Unusual line terminators are ignored.", + "unusualLineTerminators.prompt": "Unusual line terminators prompt to be removed.", + "unusualLineTerminators.title": "Unusual Line Terminators", + "useTabStops": "Inserting and deleting whitespace follows tab stops.", + "view problem": "View Problem", + "warningBorder": "Border color of warning boxes in the editor.", + "warningIcon": "Icon shown with a warning message in the extensions editor.", + "widgetShadow": "Shadow color of widgets such as find/replace inside the editor.", + "wordBasedSuggestions": "Controls whether completions should be computed based on words in the document.", + "wordBasedSuggestionsMode": "Controls from which documents word based completions are computed.", + "wordBasedSuggestionsMode.allDocuments": "Suggest words from all open documents.", + "wordBasedSuggestionsMode.currentDocument": "Only suggest words from the active document.", + "wordBasedSuggestionsMode.matchingDocuments": "Suggest words from all open documents of the same language.", + "wordHighlight": "Background color of a symbol during read-access, like reading a variable. The color must not be opaque so as not to hide underlying decorations.", + "wordHighlight.next.label": "Go to Next Symbol Highlight", + "wordHighlight.previous.label": "Go to Previous Symbol Highlight", + "wordHighlight.trigger.label": "Trigger Symbol Highlight", + "wordHighlightBorder": "Border color of a symbol during read-access, like reading a variable.", + "wordHighlightStrong": "Background color of a symbol during write-access, like writing to a variable. The color must not be opaque so as not to hide underlying decorations.", + "wordHighlightStrongBorder": "Border color of a symbol during write-access, like writing to a variable.", + "wordSeparators": "Characters that will be used as word separators when doing word related navigations or operations.", + "wordWrap.inherit": "Lines will wrap according to the `#editor.wordWrap#` setting.", + "wordWrap.off": "Lines will never wrap.", + "wordWrap.on": "Lines will wrap at the viewport width.", + "wordsDescription": "Match Whole Word", + "wrappingIndent": "Controls the indentation of wrapped lines.", + "wrappingIndent.deepIndent": "Wrapped lines get +2 indentation toward the parent.", + "wrappingIndent.indent": "Wrapped lines get +1 indentation toward the parent.", + "wrappingIndent.none": "No indentation. Wrapped lines begin at column 1.", + "wrappingIndent.same": "Wrapped lines get the same indentation as the parent.", + "wrappingStrategy": "Controls the algorithm that computes wrapping points.", + "wrappingStrategy.advanced": "Delegates wrapping points computation to the browser. This is a slow algorithm, that might cause freezes for large files, but it works correctly in all cases.", + "wrappingStrategy.simple": "Assumes that all characters are of the same width. This is a fast algorithm that works correctly for monospace fonts and certain scripts (like Latin characters) where glyphs are of equal width." } From 08f6b27cc6da79220f358e01d7d8727282e1c902 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 16:42:35 +0200 Subject: [PATCH 26/45] i18n fixup. Signed-off-by: Akos Kitta --- i18n/en.json | 1352 +------------------------------------------------- 1 file changed, 4 insertions(+), 1348 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index fbed0c51d..7d0a30505 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1,104 +1,4 @@ { - "April": "April", - "AprilShort": "Apr", - "August": "August", - "AugustShort": "Aug", - "December": "December", - "DecemberShort": "Dec", - "EditorFontZoomIn.label": "Editor Font Zoom In", - "EditorFontZoomOut.label": "Editor Font Zoom Out", - "EditorFontZoomReset.label": "Editor Font Zoom Reset", - "Error": "Error", - "February": "February", - "FebruaryShort": "Feb", - "Friday": "Friday", - "FridayShort": "Fri", - "Hint": "Hint", - "InPlaceReplaceAction.next.label": "Replace with Next Value", - "InPlaceReplaceAction.previous.label": "Replace with Previous Value", - "Info": "Info", - "January": "January", - "JanuaryShort": "Jan", - "July": "July", - "JulyShort": "Jul", - "June": "June", - "JuneShort": "Jun", - "March": "March", - "MarchShort": "Mar", - "May": "May", - "MayShort": "May", - "Monday": "Monday", - "MondayShort": "Mon", - "November": "November", - "NovemberShort": "Nov", - "October": "October", - "OctoberShort": "Oct", - "Saturday": "Saturday", - "SaturdayShort": "Sat", - "September": "September", - "SeptemberShort": "Sep", - "Sunday": "Sunday", - "SundayShort": "Sun", - "Thursday": "Thursday", - "ThursdayShort": "Thu", - "Tuesday": "Tuesday", - "TuesdayShort": "Tue", - "Warning": "Warning", - "Wednesday": "Wednesday", - "WednesdayShort": "Wed", - "accept.insert": "Insert", - "accept.replace": "Replace", - "acceptInlineSuggestion": "Accept", - "acceptSuggestionOnCommitCharacter": "Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`;`) can be a commit character that accepts a suggestion and types that character.", - "acceptSuggestionOnEnter": "Controls whether suggestions should be accepted on `Enter`, in addition to `Tab`. Helps to avoid ambiguity between inserting new lines or accepting suggestions.", - "acceptSuggestionOnEnterSmart": "Only accept a suggestion with `Enter` when it makes a textual change.", - "accessibilityHelpMessage": "Press Alt+F1 for Accessibility Options.", - "accessibilityOffAriaLabel": "The editor is not accessible at this time. Press {0} for options.", - "accessibilityPageSize": "Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 500. Warning: this has a performance implication for numbers larger than the default.", - "accessibilitySupport": "Controls whether the editor should run in a mode where it is optimized for screen readers. Setting to on will disable word wrapping.", - "accessibilitySupport.auto": "The editor will use platform APIs to detect when a Screen Reader is attached.", - "accessibilitySupport.off": "The editor will never be optimized for usage with a Screen Reader.", - "accessibilitySupport.on": "The editor will be permanently optimized for usage with a Screen Reader. Word wrapping will be disabled.", - "action.inlineSuggest.showNext": "Show Next Inline Suggestion", - "action.inlineSuggest.showPrevious": "Show Previous Inline Suggestion", - "action.inlineSuggest.trigger": "Trigger Inline Suggestion", - "action.showContextMenu.label": "Show Editor Context Menu", - "action.unicodeHighlight.disableHighlightingInComments": "Disable highlighting of characters in comments", - "action.unicodeHighlight.disableHighlightingInStrings": "Disable highlighting of characters in strings", - "action.unicodeHighlight.disableHighlightingOfAmbiguousCharacters": "Disable highlighting of ambiguous characters", - "action.unicodeHighlight.disableHighlightingOfInvisibleCharacters": "Disable highlighting of invisible characters", - "action.unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters": "Disable highlighting of non basic ASCII characters", - "action.unicodeHighlight.showExcludeOptions": "Show Exclude Options", - "actions.clipboard.copyLabel": "Copy", - "actions.clipboard.copyWithSyntaxHighlightingLabel": "Copy With Syntax Highlighting", - "actions.clipboard.cutLabel": "Cut", - "actions.clipboard.pasteLabel": "Paste", - "actions.find.isRegexOverride": "Overrides \"Use Regular Expression\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", - "actions.find.matchCaseOverride": "Overrides \"Math Case\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", - "actions.find.preserveCaseOverride": "Overrides \"Preserve Case\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", - "actions.find.wholeWordOverride": "Overrides \"Match Whole Word\" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False", - "actions.goToDecl.label": "Go to Definition", - "actions.goToDeclToSide.label": "Open Definition to the Side", - "actions.goToDeclaration.label": "Go to Declaration", - "actions.goToImplementation.label": "Go to Implementations", - "actions.goToTypeDefinition.label": "Go to Type Definition", - "actions.peekDecl.label": "Peek Declaration", - "actions.peekImplementation.label": "Peek Implementations", - "actions.peekTypeDefinition.label": "Peek Type Definition", - "actions.previewDecl.label": "Peek Definition", - "activeContrastBorder": "An extra border around active elements to separate them from others for greater contrast.", - "activeLinkForeground": "Color of active links.", - "addSelectionToNextFindMatch": "Add Selection To Next Find Match", - "addSelectionToPreviousFindMatch": "Add Selection To Previous Find Match", - "alertErrorMessage": "Error: {0}", - "alertInfoMessage": "Info: {0}", - "alertWarningMessage": "Warning: {0}", - "alternativeDeclarationCommand": "Alternative command id that is being executed when the result of 'Go to Declaration' is the current location.", - "alternativeDefinitionCommand": "Alternative command id that is being executed when the result of 'Go to Definition' is the current location.", - "alternativeImplementationCommand": "Alternative command id that is being executed when the result of 'Go to Implementation' is the current location.", - "alternativeReferenceCommand": "Alternative command id that is being executed when the result of 'Go to Reference' is the current location.", - "alternativeTypeDefinitionCommand": "Alternative command id that is being executed when the result of 'Go to Type Definition' is the current location.", - "applyCodeActionFailed": "An unknown error occurred while applying the code action", "arduino": { "about": { "detail": "Version: {0}\nDate: {1}{2}\nCLI Version: {3}{4} [{5}]\n\n{6}", @@ -416,1279 +316,35 @@ "upload": "Upload" } }, - "args.schema.apply": "Controls when the returned actions are applied.", - "args.schema.apply.first": "Always apply the first returned code action.", - "args.schema.apply.ifSingle": "Apply the first returned code action if it is the only one.", - "args.schema.apply.never": "Do not apply the returned code actions.", - "args.schema.kind": "Kind of the code action to run.", - "args.schema.preferred": "Controls if only preferred code actions should be returned.", - "aria": "Successfully renamed '{0}' to '{1}'. Summary: {2}", - "aria.alert.snippet": "Accepting '{0}' made {1} additional edits", - "ariaCurrenttSuggestionReadDetails": "{0}, docs: {1}", - "ariaSearchNoResult": "{0} found for '{1}'", - "ariaSearchNoResultEmpty": "{0} found", - "ariaSearchNoResultWithLineNum": "{0} found for '{1}', at {2}", - "ariaSearchNoResultWithLineNumNoCurrentMatch": "{0} found for '{1}'", - "autoClosingBrackets": "Controls whether the editor should automatically close brackets after the user adds an opening bracket.", - "autoClosingDelete": "Controls whether the editor should remove adjacent closing quotes or brackets when deleting.", - "autoClosingOvertype": "Controls whether the editor should type over closing quotes or brackets.", - "autoClosingQuotes": "Controls whether the editor should automatically close quotes after the user adds an opening quote.", - "autoFix.label": "Auto Fix...", - "autoIndent": "Controls whether the editor should automatically adjust the indentation when users type, paste, move or indent lines.", - "autoSurround": "Controls whether the editor should automatically surround selections when typing quotes or brackets.", - "auto_off": "The editor is configured to never be optimized for usage with a Screen Reader, which is not the case at this time.", - "auto_on": "The editor is configured to be optimized for usage with a Screen Reader.", - "badgeBackground": "Badge background color. Badges are small information labels, e.g. for search results count.", - "badgeForeground": "Badge foreground color. Badges are small information labels, e.g. for search results count.", - "blankLine": "blank", - "bracketPairColorization.enabled": "Controls whether bracket pair colorization is enabled or not. Use 'workbench.colorCustomizations' to override the bracket highlight colors.", - "breadcrumbsBackground": "Background color of breadcrumb items.", - "breadcrumbsFocusForeground": "Color of focused breadcrumb items.", - "breadcrumbsSelectedBackground": "Background color of breadcrumb item picker.", - "breadcrumbsSelectedForegound": "Color of selected breadcrumb items.", - "bulkEditServiceSummary": "Made {0} edits in {1} files", - "buttonBackground": "Button background color.", - "buttonBorder": "Button border color.", - "buttonForeground": "Button foreground color.", - "buttonHoverBackground": "Button background color when hovering.", - "buttonSecondaryBackground": "Secondary button background color.", - "buttonSecondaryForeground": "Secondary button foreground color.", - "buttonSecondaryHoverBackground": "Secondary button background color when hovering.", - "cancel": "Cancel", - "caret": "Color of the editor cursor.", - "caret.moveLeft": "Move Selected Text Left", - "caret.moveRight": "Move Selected Text Right", - "caseDescription": "Match Case", - "change": "{0} of {1} problem", - "changeAll.label": "Change All Occurrences", - "changeConfigToOnMac": "To configure the editor to be optimized for usage with a Screen Reader press Command+E now.", - "changeConfigToOnWinLinux": "To configure the editor to be optimized for usage with a Screen Reader press Control+E now.", - "chartsBlue": "The blue color used in chart visualizations.", - "chartsForeground": "The foreground color used in charts.", - "chartsGreen": "The green color used in chart visualizations.", - "chartsLines": "The color used for horizontal lines in charts.", - "chartsOrange": "The orange color used in chart visualizations.", - "chartsPurple": "The purple color used in chart visualizations.", - "chartsRed": "The red color used in chart visualizations.", - "chartsYellow": "The yellow color used in chart visualizations.", - "checkbox.background": "Background color of checkbox widget.", - "checkbox.border": "Border color of checkbox widget.", - "checkbox.foreground": "Foreground color of checkbox widget.", - "checkingForQuickFixes": "Checking for quick fixes...", "cloud": { "GoToCloud": "GO TO CLOUD" }, - "codeAction": "Show Code Actions", - "codeActionWithKb": "Show Code Actions ({0})", - "codeActions": "Enables the code action lightbulb in the editor.", - "codeLens": "Controls whether the editor shows CodeLens.", - "codeLensFontFamily": "Controls the font family for CodeLens.", - "codeLensFontSize": "Controls the font size in pixels for CodeLens. When set to `0`, 90% of `#editor.fontSize#` is used.", - "colorDecorators": "Controls whether the editor should render the inline color decorators and color picker.", - "columnSelection": "Enable that the selection with the mouse and keys is doing column selection.", - "comment.block": "Toggle Block Comment", - "comment.line": "Toggle Line Comment", - "comment.line.add": "Add Line Comment", - "comment.line.remove": "Remove Line Comment", - "comments.ignoreEmptyLines": "Controls if empty lines should be ignored with toggle, add or remove actions for line comments.", - "comments.insertSpace": "Controls whether a space character is inserted when commenting.", - "config.property.duplicate": "Cannot register '{0}'. This property is already registered.", - "config.property.empty": "Cannot register an empty property", - "config.property.languageDefault": "Cannot register '{0}'. This matches property pattern '\\[.*\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.", - "configuredTabSize": "Configured Tab Size", - "confirmDifferentSource": "Would you like to undo '{0}'?", - "confirmDifferentSource.no": "No", - "confirmDifferentSource.yes": "Yes", - "confirmWorkspace": "Would you like to undo '{0}' across all files?", - "contrastBorder": "An extra border around elements to separate them from others for greater contrast.", - "copy as": "Copy As", - "copyWithSyntaxHighlighting": "Controls whether syntax highlighting should be copied into the clipboard.", - "ctrlEnter.keybindingChanged": "Ctrl+Enter now inserts line break instead of replacing all. You can modify the keybinding for editor.action.replaceAll to override this behavior.", - "cursor.redo": "Cursor Redo", - "cursor.undo": "Cursor Undo", - "cursorAdded": "Cursor added: {0}", - "cursorBlinking": "Control the cursor animation style.", - "cursorSmoothCaretAnimation": "Controls whether the smooth caret animation should be enabled.", - "cursorStyle": "Controls the cursor style.", - "cursorSurroundingLines": "Controls the minimal number of visible leading and trailing lines surrounding the cursor. Known as 'scrollOff' or 'scrollOffset' in some other editors.", - "cursorSurroundingLinesStyle": "Controls when `cursorSurroundingLines` should be enforced.", - "cursorSurroundingLinesStyle.all": "`cursorSurroundingLines` is enforced always.", - "cursorSurroundingLinesStyle.default": "`cursorSurroundingLines` is enforced only when triggered via the keyboard or API.", - "cursorWidth": "Controls the width of the cursor when `#editor.cursorStyle#` is set to `line`.", - "cursors.maximum": "The number of cursors has been limited to {0}.", - "cursorsAdded": "Cursors added: {0}", - "debugLinuxConfiguration": "Linux specific launch configuration attributes.", - "debugName": "Name of configuration; appears in the launch configuration drop down menu.", - "debugOSXConfiguration": "OS X specific launch configuration attributes.", - "debugPostDebugTask": "Task to run after debug session ends.", - "debugPrelaunchTask": "Task to run before debug session starts.", - "debugRequest": "Request type of configuration. Can be \"launch\" or \"attach\".", - "debugServer": "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode", - "debugType": "Type of configuration.", - "debugTypeNotRecognised": "The debug type is not recognized. Make sure that you have a corresponding debug extension installed and that it is enabled.", - "debugWindowsConfiguration": "Windows specific launch configuration attributes.", - "decl.generic.noResults": "No declaration found", - "decl.noResultWord": "No declaration found for '{0}'", - "decl.title": "Declarations", - "def.title": "Definitions", - "defaultLabel": "input", - "defaultLanguageConfiguration.description": "Configure settings to be overridden for {0} language.", - "defaultLanguageConfigurationOverrides.title": "Default Language Configuration Overrides", - "definitionLinkOpensInPeek": "Controls whether the Go to Definition mouse gesture always opens the peek widget.", - "deleteInsideWord": "Delete Word", - "deleteLine": "- {0} original line {1}", - "deprecated": "This setting is deprecated, please use separate settings like 'editor.suggest.showKeywords' or 'editor.suggest.showSnippets' instead.", - "deprecatedEditorActiveLineNumber": "Id is deprecated. Use 'editorLineNumber.activeForeground' instead.", - "deprecatedVariables": "'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead.", - "descriptionForeground": "Foreground color for description text providing additional information, for example for a label.", - "detail.less": "show more", - "detail.more": "show less", - "details.close": "Close", - "detectIndentation": "Detect Indentation from Content", - "diff.clipboard.copyChangedLineContent.label": "Copy changed line ({0})", - "diff.clipboard.copyChangedLinesContent.label": "Copy changed lines", - "diff.clipboard.copyChangedLinesContent.single.label": "Copy changed line", - "diff.clipboard.copyDeletedLineContent.label": "Copy deleted line ({0})", - "diff.clipboard.copyDeletedLinesContent.label": "Copy deleted lines", - "diff.clipboard.copyDeletedLinesContent.single.label": "Copy deleted line", - "diff.inline.revertChange.label": "Revert this change", - "diff.tooLarge": "Cannot compare files because one file is too large.", - "diffDiagonalFill": "Color of the diff editor's diagonal fill. The diagonal fill is used in side-by-side diff views.", - "diffEditorBorder": "Border color between the two text editors.", - "diffEditorInserted": "Background color for text that got inserted. The color must not be opaque so as not to hide underlying decorations.", - "diffEditorInsertedLineGutter": "Background color for the margin where lines got inserted.", - "diffEditorInsertedLines": "Background color for lines that got inserted. The color must not be opaque so as not to hide underlying decorations.", - "diffEditorInsertedOutline": "Outline color for the text that got inserted.", - "diffEditorOverviewInserted": "Diff overview ruler foreground for inserted content.", - "diffEditorOverviewRemoved": "Diff overview ruler foreground for removed content.", - "diffEditorRemoved": "Background color for text that got removed. The color must not be opaque so as not to hide underlying decorations.", - "diffEditorRemovedLineGutter": "Background color for the margin where lines got removed.", - "diffEditorRemovedLines": "Background color for lines that got removed. The color must not be opaque so as not to hide underlying decorations.", - "diffEditorRemovedOutline": "Outline color for text that got removed.", - "diffInsertIcon": "Line decoration for inserts in the diff editor.", - "diffRemoveIcon": "Line decoration for removals in the diff editor.", - "diffReviewCloseIcon": "Icon for 'Close' in diff review.", - "diffReviewInsertIcon": "Icon for 'Insert' in diff review.", - "diffReviewRemoveIcon": "Icon for 'Remove' in diff review.", - "dragAndDrop": "Controls whether the editor should allow moving selections via drag and drop.", - "dropdownBackground": "Dropdown background.", - "dropdownBorder": "Dropdown border.", - "dropdownForeground": "Dropdown foreground.", - "dropdownListBackground": "Dropdown list background.", - "duplicateSelection": "Duplicate Selection", - "edit": "Typing", - "editableDiffEditor": " in a pane of a diff editor.", - "editableEditor": " in a code editor", - "editor": "editor", - "editor.action.autoFix.noneMessage": "No auto fixes available", - "editor.action.codeAction.noneMessage": "No code actions available", - "editor.action.codeAction.noneMessage.kind": "No code actions for '{0}' available", - "editor.action.codeAction.noneMessage.preferred": "No preferred code actions available", - "editor.action.codeAction.noneMessage.preferred.kind": "No preferred code actions for '{0}' available", - "editor.action.diffReview.next": "Go to Next Difference", - "editor.action.diffReview.prev": "Go to Previous Difference", - "editor.action.organize.noneMessage": "No organize imports action available", - "editor.action.quickFix.noneMessage": "No code actions available", - "editor.action.refactor.noneMessage": "No refactorings available", - "editor.action.refactor.noneMessage.kind": "No refactorings for '{0}' available", - "editor.action.refactor.noneMessage.preferred": "No preferred refactorings available", - "editor.action.refactor.noneMessage.preferred.kind": "No preferred refactorings for '{0}' available", - "editor.action.source.noneMessage": "No source actions available", - "editor.action.source.noneMessage.kind": "No source actions for '{0}' available", - "editor.action.source.noneMessage.preferred": "No preferred source actions available", - "editor.action.source.noneMessage.preferred.kind": "No preferred source actions for '{0}' available", - "editor.autoClosingBrackets.beforeWhitespace": "Autoclose brackets only when the cursor is to the left of whitespace.", - "editor.autoClosingBrackets.languageDefined": "Use language configurations to determine when to autoclose brackets.", - "editor.autoClosingDelete.auto": "Remove adjacent closing quotes or brackets only if they were automatically inserted.", - "editor.autoClosingOvertype.auto": "Type over closing quotes or brackets only if they were automatically inserted.", - "editor.autoClosingQuotes.beforeWhitespace": "Autoclose quotes only when the cursor is to the left of whitespace.", - "editor.autoClosingQuotes.languageDefined": "Use language configurations to determine when to autoclose quotes.", - "editor.autoIndent.advanced": "The editor will keep the current line's indentation, honor language defined brackets and invoke special onEnterRules defined by languages.", - "editor.autoIndent.brackets": "The editor will keep the current line's indentation and honor language defined brackets.", - "editor.autoIndent.full": "The editor will keep the current line's indentation, honor language defined brackets, invoke special onEnterRules defined by languages, and honor indentationRules defined by languages.", - "editor.autoIndent.keep": "The editor will keep the current line's indentation.", - "editor.autoIndent.none": "The editor will not insert indentation automatically.", - "editor.autoSurround.brackets": "Surround with brackets but not quotes.", - "editor.autoSurround.languageDefined": "Use language configurations to determine when to automatically surround selections.", - "editor.autoSurround.quotes": "Surround with quotes but not brackets.", - "editor.editor.gotoLocation.multipleDeclarations": "Controls the behavior the 'Go to Declaration'-command when multiple target locations exist.", - "editor.editor.gotoLocation.multipleDefinitions": "Controls the behavior the 'Go to Definition'-command when multiple target locations exist.", - "editor.editor.gotoLocation.multipleImplemenattions": "Controls the behavior the 'Go to Implementations'-command when multiple target locations exist.", - "editor.editor.gotoLocation.multipleReferences": "Controls the behavior the 'Go to References'-command when multiple target locations exist.", - "editor.editor.gotoLocation.multipleTypeDefinitions": "Controls the behavior the 'Go to Type Definition'-command when multiple target locations exist.", - "editor.find.autoFindInSelection.always": "Always turn on Find in Selection automatically.", - "editor.find.autoFindInSelection.multiline": "Turn on Find in Selection automatically when multiple lines of content are selected.", - "editor.find.autoFindInSelection.never": "Never turn on Find in Selection automatically (default).", - "editor.find.seedSearchStringFromSelection.always": "Always seed search string from the editor selection, including word at cursor position.", - "editor.find.seedSearchStringFromSelection.never": "Never seed search string from the editor selection.", - "editor.find.seedSearchStringFromSelection.selection": "Only seed search string from the editor selection.", - "editor.gotoLocation.multiple.deprecated": "This setting is deprecated, please use separate settings like 'editor.editor.gotoLocation.multipleDefinitions' or 'editor.editor.gotoLocation.multipleImplementations' instead.", - "editor.gotoLocation.multiple.goto": "Go to the primary result and enable peek-less navigation to others", - "editor.gotoLocation.multiple.gotoAndPeek": "Go to the primary result and show a peek view", - "editor.gotoLocation.multiple.peek": "Show peek view of the results (default)", - "editor.guides.bracketPairs": "Controls whether bracket pair guides are enabled or not.", - "editor.guides.bracketPairs.active": "Enables bracket pair guides only for the active bracket pair.", - "editor.guides.bracketPairs.false": "Disables bracket pair guides.", - "editor.guides.bracketPairs.true": "Enables bracket pair guides.", - "editor.guides.bracketPairsHorizontal": "Controls whether horizontal bracket pair guides are enabled or not.", - "editor.guides.bracketPairsHorizontal.active": "Enables horizontal guides only for the active bracket pair.", - "editor.guides.bracketPairsHorizontal.false": "Disables horizontal bracket pair guides.", - "editor.guides.bracketPairsHorizontal.true": "Enables horizontal guides as addition to vertical bracket pair guides.", - "editor.guides.highlightActiveBracketPair": "Controls whether the editor should highlight the active bracket pair.", - "editor.guides.highlightActiveIndentation": "Controls whether the editor should highlight the active indent guide.", - "editor.guides.indentation": "Controls whether the editor should render indent guides.", - "editor.readonly": "Cannot edit in read-only editor", - "editor.reindentlines": "Reindent Lines", - "editor.reindentselectedlines": "Reindent Selected Lines", - "editor.suggest.showClasss": "When enabled IntelliSense shows `class`-suggestions.", - "editor.suggest.showColors": "When enabled IntelliSense shows `color`-suggestions.", - "editor.suggest.showConstants": "When enabled IntelliSense shows `constant`-suggestions.", - "editor.suggest.showConstructors": "When enabled IntelliSense shows `constructor`-suggestions.", - "editor.suggest.showCustomcolors": "When enabled IntelliSense shows `customcolor`-suggestions.", - "editor.suggest.showDeprecated": "When enabled IntelliSense shows `deprecated`-suggestions.", - "editor.suggest.showEnumMembers": "When enabled IntelliSense shows `enumMember`-suggestions.", - "editor.suggest.showEnums": "When enabled IntelliSense shows `enum`-suggestions.", - "editor.suggest.showEvents": "When enabled IntelliSense shows `event`-suggestions.", - "editor.suggest.showFields": "When enabled IntelliSense shows `field`-suggestions.", - "editor.suggest.showFiles": "When enabled IntelliSense shows `file`-suggestions.", - "editor.suggest.showFolders": "When enabled IntelliSense shows `folder`-suggestions.", - "editor.suggest.showFunctions": "When enabled IntelliSense shows `function`-suggestions.", - "editor.suggest.showInterfaces": "When enabled IntelliSense shows `interface`-suggestions.", - "editor.suggest.showIssues": "When enabled IntelliSense shows `issues`-suggestions.", - "editor.suggest.showKeywords": "When enabled IntelliSense shows `keyword`-suggestions.", - "editor.suggest.showMethods": "When enabled IntelliSense shows `method`-suggestions.", - "editor.suggest.showModules": "When enabled IntelliSense shows `module`-suggestions.", - "editor.suggest.showOperators": "When enabled IntelliSense shows `operator`-suggestions.", - "editor.suggest.showPropertys": "When enabled IntelliSense shows `property`-suggestions.", - "editor.suggest.showReferences": "When enabled IntelliSense shows `reference`-suggestions.", - "editor.suggest.showSnippets": "When enabled IntelliSense shows `snippet`-suggestions.", - "editor.suggest.showStructs": "When enabled IntelliSense shows `struct`-suggestions.", - "editor.suggest.showTexts": "When enabled IntelliSense shows `text`-suggestions.", - "editor.suggest.showTypeParameters": "When enabled IntelliSense shows `typeParameter`-suggestions.", - "editor.suggest.showUnits": "When enabled IntelliSense shows `unit`-suggestions.", - "editor.suggest.showUsers": "When enabled IntelliSense shows `user`-suggestions.", - "editor.suggest.showValues": "When enabled IntelliSense shows `value`-suggestions.", - "editor.suggest.showVariables": "When enabled IntelliSense shows `variable`-suggestions.", - "editor.transformToLowercase": "Transform to Lowercase", - "editor.transformToSnakecase": "Transform to Snake Case", - "editor.transformToTitlecase": "Transform to Title Case", - "editor.transformToUppercase": "Transform to Uppercase", - "editor.transpose": "Transpose characters around the cursor", - "editorActiveIndentGuide": "Color of the active editor indentation guides.", - "editorActiveLineNumber": "Color of editor active line number", - "editorBackground": "Editor background color.", - "editorBracketHighlightForeground1": "Foreground color of brackets (1). Requires enabling bracket pair colorization.", - "editorBracketHighlightForeground2": "Foreground color of brackets (2). Requires enabling bracket pair colorization.", - "editorBracketHighlightForeground3": "Foreground color of brackets (3). Requires enabling bracket pair colorization.", - "editorBracketHighlightForeground4": "Foreground color of brackets (4). Requires enabling bracket pair colorization.", - "editorBracketHighlightForeground5": "Foreground color of brackets (5). Requires enabling bracket pair colorization.", - "editorBracketHighlightForeground6": "Foreground color of brackets (6). Requires enabling bracket pair colorization.", - "editorBracketHighlightUnexpectedBracketForeground": "Foreground color of unexpected brackets.", - "editorBracketMatchBackground": "Background color behind matching brackets", - "editorBracketMatchBorder": "Color for matching brackets boxes", - "editorBracketPairGuide.activeBackground1": "Background color of active bracket pair guides (1). Requires enabling bracket pair guides.", - "editorBracketPairGuide.activeBackground2": "Background color of active bracket pair guides (2). Requires enabling bracket pair guides.", - "editorBracketPairGuide.activeBackground3": "Background color of active bracket pair guides (3). Requires enabling bracket pair guides.", - "editorBracketPairGuide.activeBackground4": "Background color of active bracket pair guides (4). Requires enabling bracket pair guides.", - "editorBracketPairGuide.activeBackground5": "Background color of active bracket pair guides (5). Requires enabling bracket pair guides.", - "editorBracketPairGuide.activeBackground6": "Background color of active bracket pair guides (6). Requires enabling bracket pair guides.", - "editorBracketPairGuide.background1": "Background color of inactive bracket pair guides (1). Requires enabling bracket pair guides.", - "editorBracketPairGuide.background2": "Background color of inactive bracket pair guides (2). Requires enabling bracket pair guides.", - "editorBracketPairGuide.background3": "Background color of inactive bracket pair guides (3). Requires enabling bracket pair guides.", - "editorBracketPairGuide.background4": "Background color of inactive bracket pair guides (4). Requires enabling bracket pair guides.", - "editorBracketPairGuide.background5": "Background color of inactive bracket pair guides (5). Requires enabling bracket pair guides.", - "editorBracketPairGuide.background6": "Background color of inactive bracket pair guides (6). Requires enabling bracket pair guides.", - "editorCodeLensForeground": "Foreground color of editor CodeLens", - "editorColumnSelection": "Whether `editor.columnSelection` is enabled", - "editorConfigurationTitle": "Editor", - "editorCursorBackground": "The background color of the editor cursor. Allows customizing the color of a character overlapped by a block cursor.", - "editorError.background": "Background color of error text in the editor. The color must not be opaque so as not to hide underlying decorations.", - "editorError.foreground": "Foreground color of error squigglies in the editor.", - "editorFindMatch": "Color of the current search match.", - "editorFindMatchBorder": "Border color of the current search match.", - "editorFocus": "Whether the editor or an editor widget has focus (e.g. focus is in the find widget)", - "editorForeground": "Editor default foreground color.", - "editorGhostTextBackground": "Background color of the ghost text in the editor.", - "editorGhostTextBorder": "Border color of ghost text in the editor.", - "editorGhostTextForeground": "Foreground color of the ghost text in the editor.", - "editorGutter": "Background color of the editor gutter. The gutter contains the glyph margins and the line numbers.", - "editorGutter.foldingControlForeground": "Color of the folding control in the editor gutter.", - "editorHasCodeActionsProvider": "Whether the editor has a code actions provider", - "editorHasCodeLensProvider": "Whether the editor has a code lens provider", - "editorHasCompletionItemProvider": "Whether the editor has a completion item provider", - "editorHasDeclarationProvider": "Whether the editor has a declaration provider", - "editorHasDefinitionProvider": "Whether the editor has a definition provider", - "editorHasDocumentFormattingProvider": "Whether the editor has a document formatting provider", - "editorHasDocumentHighlightProvider": "Whether the editor has a document highlight provider", - "editorHasDocumentSelectionFormattingProvider": "Whether the editor has a document selection formatting provider", - "editorHasDocumentSymbolProvider": "Whether the editor has a document symbol provider", - "editorHasHoverProvider": "Whether the editor has a hover provider", - "editorHasImplementationProvider": "Whether the editor has an implementation provider", - "editorHasInlayHintsProvider": "Whether the editor has an inline hints provider", - "editorHasMultipleDocumentFormattingProvider": "Whether the editor has multiple document formatting providers", - "editorHasMultipleDocumentSelectionFormattingProvider": "Whether the editor has multiple document selection formatting providers", - "editorHasMultipleSelections": "Whether the editor has multiple selections", - "editorHasReferenceProvider": "Whether the editor has a reference provider", - "editorHasRenameProvider": "Whether the editor has a rename provider", - "editorHasSelection": "Whether the editor has text selected", - "editorHasSignatureHelpProvider": "Whether the editor has a signature help provider", - "editorHasTypeDefinitionProvider": "Whether the editor has a type definition provider", - "editorHint.foreground": "Foreground color of hint squigglies in the editor.", - "editorHoverVisible": "Whether the editor hover is visible", - "editorHoverWidgetHighlightForeground": "Foreground color of the active item in the parameter hint.", - "editorInactiveSelection": "Color of the selection in an inactive editor. The color must not be opaque so as not to hide underlying decorations.", - "editorIndentGuides": "Color of the editor indentation guides.", - "editorInfo.background": "Background color of info text in the editor. The color must not be opaque so as not to hide underlying decorations.", - "editorInfo.foreground": "Foreground color of info squigglies in the editor.", - "editorInlayHintBackground": "Background color of inline hints", - "editorInlayHintBackgroundParameter": "Background color of inline hints for parameters", - "editorInlayHintBackgroundTypes": "Background color of inline hints for types", - "editorInlayHintForeground": "Foreground color of inline hints", - "editorInlayHintForegroundParameter": "Foreground color of inline hints for parameters", - "editorInlayHintForegroundTypes": "Foreground color of inline hints for types", - "editorLangId": "The language identifier of the editor", - "editorLightBulbAutoFixForeground": "The color used for the lightbulb auto fix actions icon.", - "editorLightBulbForeground": "The color used for the lightbulb actions icon.", - "editorLineNumbers": "Color of editor line numbers.", - "editorLinkedEditingBackground": "Background color when the editor auto renames on type.", - "editorMarkerNavigationBackground": "Editor marker navigation widget background.", - "editorMarkerNavigationError": "Editor marker navigation widget error color.", - "editorMarkerNavigationErrorHeaderBackground": "Editor marker navigation widget error heading background.", - "editorMarkerNavigationInfo": "Editor marker navigation widget info color.", - "editorMarkerNavigationInfoHeaderBackground": "Editor marker navigation widget info heading background.", - "editorMarkerNavigationWarning": "Editor marker navigation widget warning color.", - "editorMarkerNavigationWarningBackground": "Editor marker navigation widget warning heading background.", - "editorOverviewRulerBackground": "Background color of the editor overview ruler. Only used when the minimap is enabled and placed on the right side of the editor.", - "editorOverviewRulerBorder": "Color of the overview ruler border.", - "editorReadonly": "Whether the editor is read only", - "editorRuler": "Color of the editor rulers.", - "editorSelectionBackground": "Color of the editor selection.", - "editorSelectionForeground": "Color of the selected text for high contrast.", - "editorSelectionHighlight": "Color for regions with the same content as the selection. The color must not be opaque so as not to hide underlying decorations.", - "editorSelectionHighlightBorder": "Border color for regions with the same content as the selection.", - "editorSuggestWidgetBackground": "Background color of the suggest widget.", - "editorSuggestWidgetBorder": "Border color of the suggest widget.", - "editorSuggestWidgetFocusHighlightForeground": "Color of the match highlights in the suggest widget when an item is focused.", - "editorSuggestWidgetForeground": "Foreground color of the suggest widget.", - "editorSuggestWidgetHighlightForeground": "Color of the match highlights in the suggest widget.", - "editorSuggestWidgetSelectedBackground": "Background color of the selected entry in the suggest widget.", - "editorSuggestWidgetSelectedForeground": "Foreground color of the selected entry in the suggest widget.", - "editorSuggestWidgetSelectedIconForeground": "Icon foreground color of the selected entry in the suggest widget.", - "editorSuggestWidgetStatusForeground": "Foreground color of the suggest widget status.", - "editorTabMovesFocus": "Whether `Tab` will move focus out of the editor", - "editorTextFocus": "Whether the editor text has focus (cursor is blinking)", - "editorUnicodeHighlight.border": "Border color used to highlight unicode characters.", - "editorViewAccessibleLabel": "Editor content", - "editorWarning.background": "Background color of warning text in the editor. The color must not be opaque so as not to hide underlying decorations.", - "editorWarning.foreground": "Foreground color of warning squigglies in the editor.", - "editorWhitespaces": "Color of whitespace characters in the editor.", - "editorWidgetBackground": "Background color of editor widgets, such as find/replace.", - "editorWidgetBorder": "Border color of editor widgets. The color is only used if the widget chooses to have a border and if the color is not overridden by a widget.", - "editorWidgetForeground": "Foreground color of editor widgets, such as find/replace.", - "editorWidgetResizeBorder": "Border color of the resize bar of editor widgets. The color is only used if the widget chooses to have a resize border and if the color is not overridden by a widget.", - "emergencyConfOn": "Now changing the setting `accessibilitySupport` to 'on'.", - "emptySelectionClipboard": "Controls whether copying without a selection copies the current line.", - "enablePreview": "Enable/disable the ability to preview changes before renaming", - "equalLine": "{0} original line {1} modified line {2}", - "error.defaultMessage": "An unknown error occurred. Please consult the log for more details.", - "error.moreErrors": "{0} ({1} errors in total)", - "errorBorder": "Border color of error boxes in the editor.", - "errorForeground": "Overall foreground color for error messages. This color is only used if not overridden by a component.", - "expandLineSelection": "Expand Line Selection", - "fastScrollSensitivity": "Scrolling speed multiplier when pressing `Alt`.", - "find.addExtraSpaceOnTop": "Controls whether the Find Widget should add extra lines on top of the editor. When true, you can scroll beyond the first line when the Find Widget is visible.", - "find.autoFindInSelection": "Controls the condition for turning on Find in Selection automatically.", - "find.cursorMoveOnType": "Controls whether the cursor should jump to find matches while typing.", - "find.globalFindClipboard": "Controls whether the Find Widget should read or modify the shared find clipboard on macOS.", - "find.loop": "Controls whether the search automatically restarts from the beginning (or the end) when no further matches can be found.", - "find.seedSearchStringFromSelection": "Controls whether the search string in the Find Widget is seeded from the editor selection.", - "findCollapsedIcon": "Icon to indicate that the editor find widget is collapsed.", - "findExpandedIcon": "Icon to indicate that the editor find widget is expanded.", - "findMatchHighlight": "Color of the other search matches. The color must not be opaque so as not to hide underlying decorations.", - "findMatchHighlightBorder": "Border color of the other search matches.", - "findNextMatchAction": "Find Next", - "findNextMatchIcon": "Icon for 'Find Next' in the editor find widget.", - "findPreviousMatchAction": "Find Previous", - "findPreviousMatchIcon": "Icon for 'Find Previous' in the editor find widget.", - "findRangeHighlight": "Color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations.", - "findRangeHighlightBorder": "Border color of the range limiting the search. The color must not be opaque so as not to hide underlying decorations.", - "findReplaceAllIcon": "Icon for 'Replace All' in the editor find widget.", - "findReplaceIcon": "Icon for 'Replace' in the editor find widget.", - "findSelectionIcon": "Icon for 'Find in Selection' in the editor find widget.", - "first.chord": "({0}) was pressed. Waiting for second key of chord...", - "fixAll.label": "Fix All", - "fixAll.noneMessage": "No fix all action available", - "focusBorder": "Overall border color for focused elements. This color is only used if not overridden by a component.", - "foldAction.label": "Fold", - "foldAllAction.label": "Fold All", - "foldAllBlockComments.label": "Fold All Block Comments", - "foldAllExcept.label": "Fold All Regions Except Selected", - "foldAllMarkerRegions.label": "Fold All Regions", - "foldBackgroundBackground": "Background color behind folded ranges. The color must not be opaque so as not to hide underlying decorations.", - "foldLevelAction.label": "Fold Level {0}", - "foldRecursivelyAction.label": "Fold Recursively", - "folding": "Controls whether the editor has code folding enabled.", - "foldingHighlight": "Controls whether the editor should highlight folded ranges.", - "foldingImportsByDefault": "Controls whether the editor automatically collapses import ranges.", - "foldingMaximumRegions": "The maximum number of foldable regions. Increasing this value may result in the editor becoming less responsive when the current source has a large number of foldable regions.", - "foldingStrategy": "Controls the strategy for computing folding ranges.", - "foldingStrategy.auto": "Use a language-specific folding strategy if available, else the indentation-based one.", - "foldingStrategy.indentation": "Use the indentation-based folding strategy.", - "fontFamily": "Controls the font family.", - "fontFeatureSettings": "Explicit 'font-feature-settings' CSS property. A boolean can be passed instead if one only needs to turn on/off ligatures.", - "fontLigatures": "Enables/Disables font ligatures ('calt' and 'liga' font features). Change this to a string for fine-grained control of the 'font-feature-settings' CSS property.", - "fontLigaturesGeneral": "Configures font ligatures or font features. Can be either a boolean to enable/disable ligatures or a string for the value of the CSS 'font-feature-settings' property.", - "fontSize": "Controls the font size in pixels.", - "fontWeight": "Controls the font weight. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000.", - "fontWeightErrorMessage": "Only \"normal\" and \"bold\" keywords or numbers between 1 and 1000 are allowed.", - "forceRetokenize": "Developer: Force Retokenize", - "foreground": "Overall foreground color. This color is only used if not overridden by a component.", - "formatDocument.label": "Format Document", - "formatOnPaste": "Controls whether the editor should automatically format the pasted content. A formatter must be available and the formatter should be able to format a range in a document.", - "formatOnType": "Controls whether the editor should automatically format the line after typing.", - "formatSelection.label": "Format Selection", - "generic.noResult": "No results for '{0}'", - "generic.noResults": "No definition found", - "generic.title": "Locations", - "glyphMargin": "Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.", - "goToImplementation.generic.noResults": "No implementation found", - "goToImplementation.noResultWord": "No implementation found for '{0}'", - "goToReferences.label": "Go to References", - "goToTypeDefinition.generic.noResults": "No type definition found", - "goToTypeDefinition.noResultWord": "No type definition found for '{0}'", - "gotoLineActionLabel": "Go to Line/Column...", - "gotoNextFold.label": "Go to Next Folding Range", - "gotoParentFold.label": "Go to Parent Fold", - "gotoPreviousFold.label": "Go to Previous Folding Range", - "helpQuickAccess": "Show all Quick Access Providers", - "hideCursorInOverviewRuler": "Controls whether the cursor should be hidden in the overview ruler.", - "highlight": "List/Tree foreground color of the match highlights when searching inside the list/tree.", - "hint": "{0}, hint", - "hint11": "Made 1 formatting edit on line {0}", - "hint1n": "Made 1 formatting edit between lines {0} and {1}", - "hintBorder": "Border color of hint boxes in the editor.", - "hintn1": "Made {0} formatting edits on line {1}", - "hintnn": "Made {0} formatting edits between lines {1} and {2}", - "hover.above": "Prefer showing hovers above the line, if there's space.", - "hover.delay": "Controls the delay in milliseconds after which the hover is shown.", - "hover.enabled": "Controls whether the hover is shown.", - "hover.sticky": "Controls whether the hover should remain visible when mouse is moved over it.", - "hoverBackground": "Background color of the editor hover.", - "hoverBorder": "Border color of the editor hover.", - "hoverForeground": "Foreground color of the editor hover.", - "hoverHighlight": "Highlight below the word for which a hover is shown. The color must not be opaque so as not to hide underlying decorations.", - "iconForeground": "The default color for icons in the workbench.", - "ignoreTrimWhitespace": "When enabled, the diff editor ignores changes in leading or trailing whitespace.", - "impl.title": "Implementations", - "inCompositeEditor": "Whether the editor is part of a larger editor (e.g. notebooks)", - "inDiffEditor": "Whether the context is a diff editor", - "inReferenceSearchEditor": "Whether the current code editor is embedded inside peek", - "indentUsingSpaces": "Indent Using Spaces", - "indentUsingTabs": "Indent Using Tabs", - "indentationToSpaces": "Convert Indentation to Spaces", - "indentationToTabs": "Convert Indentation to Tabs", - "infoBorder": "Border color of info boxes in the editor.", - "inlayHints.enable": "Enables the inlay hints in the editor.", - "inlayHints.fontFamily": "Controls font family of inlay hints in the editor. When set to empty, the `#editor.fontFamily#` is used.", - "inlayHints.fontSize": "Controls font size of inlay hints in the editor. A default of 90% of `#editor.fontSize#` is used when the configured value is less than `5` or greater than the editor font size.", - "inlineSuggest.enabled": "Controls whether to automatically show inline suggestions in the editor.", - "inlineSuggestionFollows": "Suggestion:", - "inlineSuggestionHasIndentation": "Whether the inline suggestion starts with whitespace", - "inlineSuggestionHasIndentationLessThanTabSize": "Whether the inline suggestion starts with whitespace that is less than what would be inserted by tab", - "inlineSuggestionVisible": "Whether an inline suggestion is visible", - "inputBoxActiveOptionBorder": "Border color of activated options in input fields.", - "inputBoxBackground": "Input box background.", - "inputBoxBorder": "Input box border.", - "inputBoxForeground": "Input box foreground.", - "inputOption.activeBackground": "Background hover color of options in input fields.", - "inputOption.activeForeground": "Foreground color of activated options in input fields.", - "inputOption.hoverBackground": "Background color of activated options in input fields.", - "inputPlaceholderForeground": "Input box foreground color for placeholder text.", - "inputValidationErrorBackground": "Input validation background color for error severity.", - "inputValidationErrorBorder": "Input validation border color for error severity.", - "inputValidationErrorForeground": "Input validation foreground color for error severity.", - "inputValidationInfoBackground": "Input validation background color for information severity.", - "inputValidationInfoBorder": "Input validation border color for information severity.", - "inputValidationInfoForeground": "Input validation foreground color for information severity.", - "inputValidationWarningBackground": "Input validation background color for warning severity.", - "inputValidationWarningBorder": "Input validation border color for warning severity.", - "inputValidationWarningForeground": "Input validation foreground color for warning severity.", - "insertLine": "+ {0} modified line {1}", - "insertSpaces": "Insert spaces when pressing `Tab`. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.", - "inspectTokens": "Developer: Inspect Tokens", - "internalConsoleOptions": "Controls when the internal debug console should open.", - "invalid.url": "Failed to open this link because it is not well-formed: {0}", - "invalidItemForeground": "List/Tree foreground color for invalid items, for example an unresolved root in explorer.", - "keybindingLabelBackground": "Keybinding label background color. The keybinding label is used to represent a keyboard shortcut.", - "keybindingLabelBorder": "Keybinding label border color. The keybinding label is used to represent a keyboard shortcut.", - "keybindingLabelBottomBorder": "Keybinding label border bottom color. The keybinding label is used to represent a keyboard shortcut.", - "keybindingLabelForeground": "Keybinding label foreground color. The keybinding label is used to represent a keyboard shortcut.", - "label": "Renaming '{0}'", - "label.close": "Close", - "label.closeButton": "Close", - "label.desc": "{0}, {1}", - "label.detail": "{0}{1}", - "label.find": "Find", - "label.full": "{0}{1}, {2}", - "label.generic": "Go to Any Symbol", - "label.matchesLocation": "{0} of {1}", - "label.nextMatchButton": "Next Match", - "label.noResults": "No results", - "label.preserveCaseCheckbox": "Preserve Case", - "label.previousMatchButton": "Previous Match", - "label.replace": "Replace", - "label.replaceAllButton": "Replace All", - "label.replaceButton": "Replace", - "label.toggleReplaceButton": "Toggle Replace", - "label.toggleSelectionFind": "Find in Selection", - "labelLoading": "Loading...", - "largeFileOptimizations": "Special handling for large files to disable certain memory intensive features.", - "letterSpacing": "Controls the letter spacing in pixels.", - "lineHeight": "Controls the line height. \n - Use 0 to automatically compute the line height from the font size.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values.", - "lineHighlight": "Background color for the highlight of line at the cursor position.", - "lineHighlightBorderBox": "Background color for the border around the line at the cursor position.", - "lineNumbers": "Controls the display of line numbers.", - "lineNumbers.interval": "Line numbers are rendered every 10 lines.", - "lineNumbers.off": "Line numbers are not rendered.", - "lineNumbers.on": "Line numbers are rendered as absolute number.", - "lineNumbers.relative": "Line numbers are rendered as distance in lines to cursor position.", - "lines.copyDown": "Copy Line Down", - "lines.copyUp": "Copy Line Up", - "lines.delete": "Delete Line", - "lines.deleteAllLeft": "Delete All Left", - "lines.deleteAllRight": "Delete All Right", - "lines.deleteDuplicates": "Delete Duplicate Lines", - "lines.indent": "Indent Line", - "lines.insertAfter": "Insert Line Below", - "lines.insertBefore": "Insert Line Above", - "lines.joinLines": "Join Lines", - "lines.moveDown": "Move Line Down", - "lines.moveUp": "Move Line Up", - "lines.outdent": "Outdent Line", - "lines.sortAscending": "Sort Lines Ascending", - "lines.sortDescending": "Sort Lines Descending", - "lines.trimTrailingWhitespace": "Trim Trailing Whitespace", - "linkedEditing": "Controls whether the editor has linked editing enabled. Depending on the language, related symbols, e.g. HTML tags, are updated while editing.", - "linkedEditing.label": "Start Linked Editing", - "links": "Controls whether the editor should detect links and make them clickable.", - "links.navigate.executeCmd": "Execute command", - "links.navigate.follow": "Follow link", - "links.navigate.kb.alt": "alt + click", - "links.navigate.kb.alt.mac": "option + click", - "links.navigate.kb.meta": "ctrl + click", - "links.navigate.kb.meta.mac": "cmd + click", - "listActiveSelectionBackground": "List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", - "listActiveSelectionForeground": "List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", - "listActiveSelectionIconForeground": "List/Tree icon foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", - "listDeemphasizedForeground": "List/Tree foreground color for items that are deemphasized. ", - "listDropBackground": "List/Tree drag and drop background when moving items around using the mouse.", - "listErrorForeground": "Foreground color of list items containing errors.", - "listFilterMatchHighlight": "Background color of the filtered match.", - "listFilterMatchHighlightBorder": "Border color of the filtered match.", - "listFilterWidgetBackground": "Background color of the type filter widget in lists and trees.", - "listFilterWidgetNoMatchesOutline": "Outline color of the type filter widget in lists and trees, when there are no matches.", - "listFilterWidgetOutline": "Outline color of the type filter widget in lists and trees.", - "listFocusBackground": "List/Tree background color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", - "listFocusForeground": "List/Tree foreground color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", - "listFocusHighlightForeground": "List/Tree foreground color of the match highlights on actively focused items when searching inside the list/tree.", - "listFocusOutline": "List/Tree outline color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.", - "listHoverBackground": "List/Tree background when hovering over items using the mouse.", - "listHoverForeground": "List/Tree foreground when hovering over items using the mouse.", - "listInactiveFocusBackground": "List/Tree background color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", - "listInactiveFocusOutline": "List/Tree outline color for the focused item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", - "listInactiveSelectionBackground": "List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", - "listInactiveSelectionForeground": "List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", - "listInactiveSelectionIconForeground": "List/Tree icon foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.", - "listWarningForeground": "Foreground color of list items containing warnings.", - "loading": "Loading...", - "marker aria": "{0} at {1}. ", - "markerAction.next.label": "Go to Next Problem (Error, Warning, Info)", - "markerAction.nextInFiles.label": "Go to Next Problem in Files (Error, Warning, Info)", - "markerAction.previous.label": "Go to Previous Problem (Error, Warning, Info)", - "markerAction.previousInFiles.label": "Go to Previous Problem in Files (Error, Warning, Info)", - "matchBrackets": "Highlight matching brackets.", - "maxComputationTime": "Timeout in milliseconds after which diff computation is cancelled. Use 0 for no timeout.", - "maxFileSize": "Maximum file size in MB for which to compute diffs. Use 0 for no limit.", - "maxTokenizationLineLength": "Lines above this length will not be tokenized for performance reasons", - "maximum fold ranges": "The number of foldable regions is limited to a maximum of {0}. Increase configuration option ['Folding Maximum Regions'](command:workbench.action.openSettings?[\"editor.foldingMaximumRegions\"]) to enable more.", - "menuBackground": "Background color of menu items.", - "menuBorder": "Border color of menus.", - "menuForeground": "Foreground color of menu items.", - "menuSelectionBackground": "Background color of the selected menu item in menus.", - "menuSelectionBorder": "Border color of the selected menu item in menus.", - "menuSelectionForeground": "Foreground color of the selected menu item in menus.", - "menuSeparatorBackground": "Color of a separator menu item in menus.", - "mergeBorder": "Border color on headers and the splitter in inline merge-conflicts.", - "mergeCommonContentBackground": "Common ancestor content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", - "mergeCommonHeaderBackground": "Common ancestor header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", - "mergeCurrentContentBackground": "Current content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", - "mergeCurrentHeaderBackground": "Current header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", - "mergeIncomingContentBackground": "Incoming content background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", - "mergeIncomingHeaderBackground": "Incoming header background in inline merge-conflicts. The color must not be opaque so as not to hide underlying decorations.", - "messageVisible": "Whether the editor is currently showing an inline message", - "metaTitle.N": "{0} ({1})", - "minimap.enabled": "Controls whether the minimap is shown.", - "minimap.maxColumn": "Limit the width of the minimap to render at most a certain number of columns.", - "minimap.renderCharacters": "Render the actual characters on a line as opposed to color blocks.", - "minimap.scale": "Scale of content drawn in the minimap: 1, 2 or 3.", - "minimap.showSlider": "Controls when the minimap slider is shown.", - "minimap.side": "Controls the side where to render the minimap.", - "minimap.size": "Controls the size of the minimap.", - "minimap.size.fill": "The minimap will stretch or shrink as necessary to fill the height of the editor (no scrolling).", - "minimap.size.fit": "The minimap will shrink as necessary to never be larger than the editor (no scrolling).", - "minimap.size.proportional": "The minimap has the same size as the editor contents (and might scroll).", - "minimapBackground": "Minimap background color.", - "minimapError": "Minimap marker color for errors.", - "minimapFindMatchHighlight": "Minimap marker color for find matches.", - "minimapForegroundOpacity": "Opacity of foreground elements rendered in the minimap. For example, \"#000000c0\" will render the elements with 75% opacity.", - "minimapSelectionHighlight": "Minimap marker color for the editor selection.", - "minimapSelectionOccurrenceHighlight": "Minimap marker color for repeating editor selections.", - "minimapSliderActiveBackground": "Minimap slider background color when clicked on.", - "minimapSliderBackground": "Minimap slider background color.", - "minimapSliderHoverBackground": "Minimap slider background color when hovering.", - "missing.chord": "The key combination ({0}, {1}) is not a command.", - "missing.url": "Failed to open this link because its target is missing.", - "missingPreviewMessage": "no preview available", - "modesContentHover.loading": "Loading...", - "more_lines_changed": "{0} lines changed", - "mouseWheelScrollSensitivity": "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.", - "mouseWheelZoom": "Zoom the font of the editor when using mouse wheel and holding `Ctrl`.", - "moveSelectionToNextFindMatch": "Move Last Selection To Next Find Match", - "moveSelectionToPreviousFindMatch": "Move Last Selection To Previous Find Match", - "multiCursorMergeOverlapping": "Merge multiple cursors when they are overlapping.", - "multiCursorModifier.alt": "Maps to `Alt` on Windows and Linux and to `Option` on macOS.", - "multiCursorModifier.ctrlCmd": "Maps to `Control` on Windows and Linux and to `Command` on macOS.", - "multiCursorPaste": "Controls pasting when the line count of the pasted text matches the cursor count.", - "multiCursorPaste.full": "Each cursor pastes the full text.", - "multiCursorPaste.spread": "Each cursor pastes a single line of the text.", - "multiSelection": "{0} selections", - "multiSelectionRange": "{0} selections ({1} characters selected)", - "multipleResults": "Click to show {0} definitions.", - "mutlicursor.addCursorsToBottom": "Add Cursors To Bottom", - "mutlicursor.addCursorsToTop": "Add Cursors To Top", - "mutlicursor.insertAbove": "Add Cursor Above", - "mutlicursor.insertAtEndOfEachLineSelected": "Add Cursors to Line Ends", - "mutlicursor.insertBelow": "Add Cursor Below", - "nextMarkerIcon": "Icon for goto next marker.", - "nextSelectionMatchFindAction": "Find Next Selection", - "no result": "No result.", - "noQuickFixes": "No quick fixes available", - "noResultWord": "No definition found for '{0}'", - "noResults": "No results", - "noSelection": "No selection", - "no_lines_changed": "no lines changed", - "node2NotSupported": "\"node2\" is no longer supported, use \"node\" instead and set the \"protocol\" attribute to \"inspector\".", - "nodeExceptionMessage": "A system error occurred ({0})", - "nok": "Undo this File", - "occurrencesHighlight": "Controls whether the editor should highlight semantic symbol occurrences.", - "one_line_changed": "1 line changed", - "openDocMac": "Press Command+H now to open a browser window with more information related to editor accessibility.", - "openDocWinLinux": "Press Control+H now to open a browser window with more information related to editor accessibility.", - "openingDocs": "Now opening the Editor Accessibility documentation page.", - "organizeImports.label": "Organize Imports", - "outroMsg": "You can dismiss this tooltip and return to the editor by pressing Escape or Shift+Escape.", - "overrideSettings.defaultDescription": "Configure editor settings to be overridden for a language.", - "overrideSettings.errorMessage": "This setting does not support per-language configuration.", - "overviewRuleError": "Overview ruler marker color for errors.", - "overviewRuleInfo": "Overview ruler marker color for infos.", - "overviewRuleWarning": "Minimap marker color for warnings.", - "overviewRulerBorder": "Controls whether a border should be drawn around the overview ruler.", - "overviewRulerBracketMatchForeground": "Overview ruler marker color for matching brackets.", - "overviewRulerCommonContentForeground": "Common ancestor overview ruler foreground for inline merge-conflicts.", - "overviewRulerCurrentContentForeground": "Current overview ruler foreground for inline merge-conflicts.", - "overviewRulerFindMatchForeground": "Overview ruler marker color for find matches. The color must not be opaque so as not to hide underlying decorations.", - "overviewRulerIncomingContentForeground": "Incoming overview ruler foreground for inline merge-conflicts.", - "overviewRulerRangeHighlight": "Overview ruler marker color for range highlights. The color must not be opaque so as not to hide underlying decorations.", - "overviewRulerSelectionHighlightForeground": "Overview ruler marker color for selection highlights. The color must not be opaque so as not to hide underlying decorations.", - "overviewRulerWordHighlightForeground": "Overview ruler marker color for symbol highlights. The color must not be opaque so as not to hide underlying decorations.", - "overviewRulerWordHighlightStrongForeground": "Overview ruler marker color for write-access symbol highlights. The color must not be opaque so as not to hide underlying decorations.", - "padding.bottom": "Controls the amount of space between the bottom edge of the editor and the last line.", - "padding.top": "Controls the amount of space between the top edge of the editor and the first line.", - "parameterHints.cycle": "Controls whether the parameter hints menu cycles or closes when reaching the end of the list.", - "parameterHints.enabled": "Enables a pop-up that shows parameter documentation and type information as you type.", - "parameterHints.trigger.label": "Trigger Parameter Hints", - "parameterHintsNextIcon": "Icon for show next parameter hint.", - "parameterHintsPreviousIcon": "Icon for show previous parameter hint.", - "peek.submenu": "Peek", - "peekView.alternateTitle": "References", - "peekViewBorder": "Color of the peek view borders and arrow.", - "peekViewEditorBackground": "Background color of the peek view editor.", - "peekViewEditorGutterBackground": "Background color of the gutter in the peek view editor.", - "peekViewEditorMatchHighlight": "Match highlight color in the peek view editor.", - "peekViewEditorMatchHighlightBorder": "Match highlight border in the peek view editor.", - "peekViewResultsBackground": "Background color of the peek view result list.", - "peekViewResultsFileForeground": "Foreground color for file nodes in the peek view result list.", - "peekViewResultsMatchForeground": "Foreground color for line nodes in the peek view result list.", - "peekViewResultsMatchHighlight": "Match highlight color in the peek view result list.", - "peekViewResultsSelectionBackground": "Background color of the selected entry in the peek view result list.", - "peekViewResultsSelectionForeground": "Foreground color of the selected entry in the peek view result list.", - "peekViewTitleBackground": "Background color of the peek view title area.", - "peekViewTitleForeground": "Color of the peek view title.", - "peekViewTitleInfoForeground": "Color of the peek view title info.", - "peekWidgetDefaultFocus": "Controls whether to focus the inline editor or the tree in the peek widget.", - "peekWidgetDefaultFocus.editor": "Focus the editor when opening peek", - "peekWidgetDefaultFocus.tree": "Focus the tree when opening peek", - "pickerBackground": "Quick picker background color. The quick picker widget is the container for pickers like the command palette.", - "pickerForeground": "Quick picker foreground color. The quick picker widget is the container for pickers like the command palette.", - "pickerGroupBorder": "Quick picker color for grouping borders.", - "pickerGroupForeground": "Quick picker color for grouping labels.", - "pickerTitleBackground": "Quick picker title background color. The quick picker widget is the container for pickers like the command palette.", - "placeholder.find": "Find", - "placeholder.replace": "Replace", - "plainText.alias": "Plain Text", - "preferredcodeActionWithKb": "Show Code Actions. Preferred Quick Fix Available ({0})", - "previousMarkerIcon": "Icon for goto previous marker.", - "previousSelectionMatchFindAction": "Find Previous Selection", - "problems": "{0} of {1} problems", - "problemsErrorIconForeground": "The color used for the problems error icon.", - "problemsInfoIconForeground": "The color used for the problems info icon.", - "problemsWarningIconForeground": "The color used for the problems warning icon.", - "progressBarBackground": "Background color of the progress bar that can show for long running operations.", - "quick fixes": "Quick Fix...", - "quickCommandActionHelp": "Show And Run Commands", - "quickCommandActionLabel": "Command Palette", - "quickInput.list.focusBackground deprecation": "Please use quickInputList.focusBackground instead", - "quickInput.listFocusBackground": "Quick picker background color for the focused item.", - "quickInput.listFocusForeground": "Quick picker foreground color for the focused item.", - "quickInput.listFocusIconForeground": "Quick picker icon foreground color for the focused item.", - "quickOutlineActionLabel": "Go to Symbol...", - "quickOutlineByCategoryActionLabel": "Go to Symbol by Category...", - "quickSuggestions": "Controls whether suggestions should automatically show up while typing.", - "quickSuggestions.comments": "Enable quick suggestions inside comments.", - "quickSuggestions.other": "Enable quick suggestions outside of strings and comments.", - "quickSuggestions.strings": "Enable quick suggestions inside strings.", - "quickSuggestionsDelay": "Controls the delay in milliseconds after which quick suggestions will show up.", - "quickfix.trigger.label": "Quick Fix...", - "quotableLabel": "Renaming {0}", - "rangeHighlight": "Background color of highlighted ranges, like by quick open and find features. The color must not be opaque so as not to hide underlying decorations.", - "rangeHighlightBorder": "Background color of the border around highlighted ranges.", - "readMore": "Read More", - "readonlyDiffEditor": " in a read-only pane of a diff editor.", - "readonlyEditor": " in a read-only code editor", - "redo": "Redo", - "ref.title": "References", - "refactor.label": "Refactor...", - "referenceSearchVisible": "Whether reference peek is visible, like 'Peek References' or 'Peek Definition'", - "references.action.label": "Peek References", - "references.no": "No references found for '{0}'", - "references.noGeneric": "No references found", - "regexDescription": "Use Regular Expression", - "removedCursor": "Removed secondary cursors", - "rename.failed": "Rename failed to compute edits", - "rename.failedApply": "Rename failed to apply edits", - "rename.label": "Rename Symbol", - "renameOnType": "Controls whether the editor auto renames on type.", - "renameOnTypeDeprecate": "Deprecated, use `editor.linkedEditing` instead.", - "renderControlCharacters": "Controls whether the editor should render control characters.", - "renderFinalNewline": "Render last line number when the file ends with a newline.", - "renderIndicators": "Controls whether the diff editor shows +/- indicators for added/removed changes.", - "renderLineHighlight": "Controls how the editor should render the current line highlight.", - "renderLineHighlight.all": "Highlights both the gutter and the current line.", - "renderLineHighlightOnlyWhenFocus": "Controls if the editor should render the current line highlight only when the editor is focused.", - "renderWhitespace": "Controls how the editor should render whitespace characters.", - "renderWhitespace.boundary": "Render whitespace characters except for single spaces between words.", - "renderWhitespace.selection": "Render whitespace characters only on selected text.", - "renderWhitespace.trailing": "Render only trailing whitespace characters.", - "resolveRenameLocationFailed": "An unknown error occurred while resolving rename location", - "roundedSelection": "Controls whether selections should have rounded corners.", - "rulers": "Render vertical rulers after a certain number of monospace characters. Use multiple values for multiple rulers. No rulers are drawn if array is empty.", - "rulers.color": "Color of this editor ruler.", - "rulers.size": "Number of monospace characters at which this editor ruler will render.", - "sashActiveBorder": "Border color of active sashes.", - "schema.brackets": "Defines the bracket symbols that increase or decrease the indentation.", - "schema.closeBracket": "The closing bracket character or string sequence.", - "schema.colorizedBracketPairs": "Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled.", - "schema.openBracket": "The opening bracket character or string sequence.", - "scrollBeyondLastColumn": "Controls the number of extra characters beyond which the editor will scroll horizontally.", - "scrollBeyondLastLine": "Controls whether the editor will scroll beyond the last line.", - "scrollPredominantAxis": "Scroll only along the predominant axis when scrolling both vertically and horizontally at the same time. Prevents horizontal drift when scrolling vertically on a trackpad.", - "scrollbar.horizontal": "Controls the visibility of the horizontal scrollbar.", - "scrollbar.horizontal.auto": "The horizontal scrollbar will be visible only when necessary.", - "scrollbar.horizontal.fit": "The horizontal scrollbar will always be hidden.", - "scrollbar.horizontal.visible": "The horizontal scrollbar will always be visible.", - "scrollbar.horizontalScrollbarSize": "The height of the horizontal scrollbar.", - "scrollbar.scrollByPage": "Controls whether clicks scroll by page or jump to click position.", - "scrollbar.vertical": "Controls the visibility of the vertical scrollbar.", - "scrollbar.vertical.auto": "The vertical scrollbar will be visible only when necessary.", - "scrollbar.vertical.fit": "The vertical scrollbar will always be hidden.", - "scrollbar.vertical.visible": "The vertical scrollbar will always be visible.", - "scrollbar.verticalScrollbarSize": "The width of the vertical scrollbar.", - "scrollbarShadow": "Scrollbar shadow to indicate that the view is scrolled.", - "scrollbarSliderActiveBackground": "Scrollbar slider background color when clicked on.", - "scrollbarSliderBackground": "Scrollbar slider background color.", - "scrollbarSliderHoverBackground": "Scrollbar slider background color when hovering.", - "searchEditor.editorFindMatchBorder": "Border color of the Search Editor query matches.", - "searchEditor.queryMatch": "Color of the Search Editor query matches.", - "selectAll": "Select All", - "selectAllOccurrencesOfFindMatch": "Select All Occurrences of Find Match", - "selectLeadingAndTrailingWhitespace": "Whether leading and trailing whitespace should always be selected.", - "selectionBackground": "The background color of text selections in the workbench (e.g. for input fields or text areas). Note that this does not apply to selections within the editor.", - "selectionClipboard": "Controls whether the Linux primary clipboard should be supported.", - "selectionHighlight": "Controls whether the editor should highlight matches similar to the selection.", - "semanticHighlighting.configuredByTheme": "Semantic highlighting is configured by the current color theme's `semanticHighlighting` setting.", - "semanticHighlighting.enabled": "Controls whether the semanticHighlighting is shown for the languages that support it.", - "semanticHighlighting.false": "Semantic highlighting disabled for all color themes.", - "semanticHighlighting.true": "Semantic highlighting enabled for all color themes.", - "showAccessibilityHelpAction": "Show Accessibility Help", - "showDeprecated": "Controls strikethrough deprecated variables.", - "showFoldingControls": "Controls when the folding controls on the gutter are shown.", - "showFoldingControls.always": "Always show the folding controls.", - "showFoldingControls.mouseover": "Only show the folding controls when the mouse is over the gutter.", - "showNextInlineSuggestion": "Next", - "showPreviousInlineSuggestion": "Previous", - "showUnused": "Controls fading out of unused code.", - "sideBySide": "Controls whether the diff editor shows the diff side by side or inline.", - "singleSelection": "Line {0}, Column {1}", - "singleSelectionRange": "Line {0}, Column {1} ({2} selected)", - "smartSelect.expand": "Expand Selection", - "smartSelect.jumpBracket": "Go to Bracket", - "smartSelect.selectToBracket": "Select to Bracket", - "smartSelect.shrink": "Shrink Selection", - "smoothScrolling": "Controls whether the editor will scroll using an animation.", - "snippetFinalTabstopHighlightBackground": "Highlight background color of the final tabstop of a snippet.", - "snippetFinalTabstopHighlightBorder": "Highlight border color of the final tabstop of a snippet.", - "snippetSuggestions": "Controls whether snippets are shown with other suggestions and how they are sorted.", - "snippetSuggestions.bottom": "Show snippet suggestions below other suggestions.", - "snippetSuggestions.inline": "Show snippets suggestions with other suggestions.", - "snippetSuggestions.none": "Do not show snippet suggestions.", - "snippetSuggestions.top": "Show snippet suggestions on top of other suggestions.", - "snippetTabstopHighlightBackground": "Highlight background color of a snippet tabstop.", - "snippetTabstopHighlightBorder": "Highlight border color of a snippet tabstop.", - "source.label": "Source Action...", - "stablePeek": "Keep peek editors open even when double clicking their content or when hitting `Escape`.", - "stackTrace.format": "{0}: {1}", - "startFindAction": "Find", - "startFindWithArgsAction": "Find With Arguments", - "startFindWithSelectionAction": "Find With Selection", - "startReplace": "Replace", - "statusBarBackground": "Background color of the editor hover status bar.", - "stickyTabStops": "Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.", - "stickydesc": "Stick to the end even when going to longer lines", - "submenu.empty": "(empty)", - "suggest": "Suggest", - "suggest.filterGraceful": "Controls whether filtering and sorting suggestions accounts for small typos.", - "suggest.insertMode": "Controls whether words are overwritten when accepting completions. Note that this depends on extensions opting into this feature.", - "suggest.insertMode.insert": "Insert suggestion without overwriting text right of the cursor.", - "suggest.insertMode.replace": "Insert suggestion and overwrite text right of the cursor.", - "suggest.localityBonus": "Controls whether sorting favors words that appear close to the cursor.", - "suggest.maxVisibleSuggestions.dep": "This setting is deprecated. The suggest widget can now be resized.", - "suggest.preview": "Controls whether to preview the suggestion outcome in the editor.", - "suggest.reset.label": "Reset Suggest Widget Size", - "suggest.shareSuggestSelections": "Controls whether remembered suggestion selections are shared between multiple workspaces and windows (needs `#editor.suggestSelection#`).", - "suggest.showIcons": "Controls whether to show or hide icons in suggestions.", - "suggest.showInlineDetails": "Controls whether suggest details show inline with the label or only in the details widget", - "suggest.showStatusBar": "Controls the visibility of the status bar at the bottom of the suggest widget.", - "suggest.snippetsPreventQuickSuggestions": "Controls whether an active snippet prevents quick suggestions.", - "suggest.trigger.label": "Trigger Suggest", - "suggestFontSize": "Font size for the suggest widget. When set to `0`, the value of `#editor.fontSize#` is used.", - "suggestLineHeight": "Line height for the suggest widget. When set to `0`, the value of `#editor.lineHeight#` is used. The minimum value is 8.", - "suggestMoreInfoIcon": "Icon for more information in the suggest widget.", - "suggestOnTriggerCharacters": "Controls whether suggestions should automatically show up when typing trigger characters.", - "suggestSelection": "Controls how suggestions are pre-selected when showing the suggest list.", - "suggestSelection.first": "Always select the first suggestion.", - "suggestSelection.recentlyUsed": "Select recent suggestions unless further typing selects one, e.g. `console.| -> console.log` because `log` has been completed recently.", - "suggestSelection.recentlyUsedByPrefix": "Select suggestions based on previous prefixes that have completed those suggestions, e.g. `co -> console` and `con -> const`.", - "suggestWidget.loading": "Loading...", - "suggestWidget.noSuggestions": "No suggestions.", - "symbolHighlight": "Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations.", - "symbolHighlightBorder": "Background color of the border around highlighted symbols.", - "tabCompletion": "Enables tab completions.", - "tabCompletion.off": "Disable tab completions.", - "tabCompletion.on": "Tab complete will insert the best matching suggestion when pressing tab.", - "tabCompletion.onlySnippets": "Tab complete snippets when their prefix match. Works best when 'quickSuggestions' aren't enabled.", - "tabFocusModeOffMsg": "Pressing Tab in the current editor will insert the tab character. Toggle this behavior by pressing {0}.", - "tabFocusModeOffMsgNoKb": "Pressing Tab in the current editor will insert the tab character. The command {0} is currently not triggerable by a keybinding.", - "tabFocusModeOnMsg": "Pressing Tab in the current editor will move focus to the next focusable element. Toggle this behavior by pressing {0}.", - "tabFocusModeOnMsgNoKb": "Pressing Tab in the current editor will move focus to the next focusable element. The command {0} is currently not triggerable by a keybinding.", - "tabSize": "The number of spaces a tab is equal to. This setting is overridden based on the file contents when `#editor.detectIndentation#` is on.", - "tableColumnsBorder": "Table border color between columns.", - "tableOddRowsBackgroundColor": "Background color for odd table rows.", - "textBlockQuoteBackground": "Background color for block quotes in text.", - "textBlockQuoteBorder": "Border color for block quotes in text.", - "textCodeBlockBackground": "Background color for code blocks in text.", - "textInputFocus": "Whether an editor or a rich text input has focus (cursor is blinking)", - "textLinkActiveForeground": "Foreground color for links in text when clicked on and on mouse hover.", - "textLinkForeground": "Foreground color for links in text.", - "textPreformatForeground": "Foreground color for preformatted text segments.", - "textSeparatorForeground": "Color for text separators.", "theia": { - "callhierarchy": { - "open": "Open Call Hierarchy" - }, "core": { "cannotConnectBackend": "Cannot connect to the backend.", "cannotConnectDaemon": "Cannot connect to the CLI daemon.", - "common": { - "closeAll": "Close All Tabs", - "closeAllTabMain": "Close All Tabs in Main Area", - "closeOtherTabMain": "Close Other Tabs in Main Area", - "closeOthers": "Close Other Tabs", - "closeRight": "Close Tabs to the Right", - "closeTab": "Close Tab", - "closeTabMain": "Close Tab in Main Area", - "collapseAllTabs": "Collapse All Side Panels", - "collapseBottomPanel": "Toggle Bottom Panel", - "collapseTab": "Collapse Side Panel", - "showNextTabGroup": "Switch to Next Tab Group", - "showNextTabInGroup": "Switch to Next Tab in Group", - "showPreviousTabGroup": "Switch to Previous Tab Group", - "showPreviousTabInGroup": "Switch to Previous Tab in Group", - "toggleMaximized": "Toggle Maximized" - }, "couldNotSave": "Could not save the sketch. Please copy your unsaved work into your favorite text editor, and restart the IDE.", "daemonOffline": "CLI Daemon Offline", - "file": { - "browse": "Browse" - }, - "highlightModifiedTabs": "Controls whether a top border is drawn on modified (dirty) editor tabs or not.", - "keyboard": { - "choose": "Choose Keyboard Layout", - "chooseLayout": "Choose a keyboard layout", - "current": "(current: {0})", - "currentLayout": " - current layout", - "mac": "Mac Keyboards", - "pc": "PC Keyboards", - "tryDetect": "Try to detect the keyboard layout from browser information and pressed keys." - }, - "offline": "Offline", - "quitMessage": "Any unsaved changes will not be saved.", - "quitTitle": "Are you sure you want to quit?", - "resetWorkbenchLayout": "Reset Workbench Layout", - "sashDelay": "Controls the hover feedback delay in milliseconds of the dragging area in between views/editors.", - "sashSize": "Controls the feedback area size in pixels of the dragging area in between views/editors. Set it to a larger value if needed.", - "silentNotifications": "Controls whether to suppress notification popups." + "offline": "Offline" }, "debug": { - "addConfigurationPlaceholder": "Select workspace root to add configuration to", - "continueAll": "Continue All", - "copyExpressionValue": "Copy Expression Value", - "debugViewLocation": "Controls the location of the debug view.", - "openBottom": "Open Bottom", - "openLeft": "Open Left", - "openRight": "Open Right", - "pauseAll": "Pause All", - "reveal": "Reveal", "start": "Start...", "startError": "There was an error starting the debug session, check the logs for more details.", - "threads": "Threads", - "toggleTracing": "Enable/disable tracing communications with debug adapters", "typeNotSupported": "The debug session type \"{0}\" is not supported." }, "editor": { - "diffEditor.maxFileSize": "Maximum file size in MB for which to compute diffs. Use 0 for no limit.", - "editor.accessibilityPageSize": "Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 500. Warning: this has a performance implication for numbers larger than the default.", - "editor.autoClosingDelete": "Controls whether the editor should remove adjacent closing quotes or brackets when deleting.", - "editor.autoClosingDelete1": "Remove adjacent closing quotes or brackets only if they were automatically inserted.", - "editor.bracketPairColorization.enabled": "Controls whether bracket pair colorization is enabled or not. Use 'workbench.colorCustomizations' to override the bracket highlight colors.", - "editor.codeLensFontSize": "Controls the font size in pixels for CodeLens. When set to `0`, 90% of `#editor.fontSize#` is used.", - "editor.find.autoFindInSelection0": "Never turn on Find in Selection automatically (default).", - "editor.find.autoFindInSelection1": "Always turn on Find in Selection automatically.", - "editor.find.seedSearchStringFromSelection0": "Never seed search string from the editor selection.", - "editor.find.seedSearchStringFromSelection1": "Always seed search string from the editor selection, including word at cursor position.", - "editor.find.seedSearchStringFromSelection2": "Only seed search string from the editor selection.", - "editor.foldingImportsByDefault": "Controls whether the editor automatically collapses import ranges.", - "editor.foldingMaximumRegions": "The maximum number of foldable regions. Increasing this value may result in the editor becoming less responsive when the current source has a large number of foldable regions.", - "editor.formatOnSaveMode.modificationsIfAvailable": "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted.", - "editor.guides.bracketPairs": "Controls whether bracket pair guides are enabled or not.", - "editor.guides.bracketPairs0": "Enables bracket pair guides.", - "editor.guides.bracketPairs1": "Enables bracket pair guides only for the active bracket pair.", - "editor.guides.bracketPairs2": "Disables bracket pair guides.", - "editor.guides.bracketPairsHorizontal": "Controls whether horizontal bracket pair guides are enabled or not.", - "editor.guides.bracketPairsHorizontal0": "Enables horizontal guides as addition to vertical bracket pair guides.", - "editor.guides.bracketPairsHorizontal1": "Enables horizontal guides only for the active bracket pair.", - "editor.guides.bracketPairsHorizontal2": "Disables horizontal bracket pair guides.", - "editor.guides.highlightActiveBracketPair": "Controls whether the editor should highlight the active bracket pair.", - "editor.hover.above": "Prefer showing hovers above the line, if there's space.", - "editor.inlayHints.enabled": "Enables the inlay hints in the editor.", - "editor.inlayHints.fontFamily": "Controls font family of inlay hints in the editor. When set to empty, the `#editor.fontFamily#` is used.", - "editor.inlayHints.fontSize": "Controls font size of inlay hints in the editor. A default of 90% of `#editor.fontSize#` is used when the configured value is less than `5` or greater than the editor font size.", - "editor.inlineSuggest.enabled": "Controls whether to automatically show inline suggestions in the editor.", - "editor.language.colorizedBracketPairs": "Defines the bracket pairs that are colorized by their nesting level if bracket pair colorization is enabled.", - "editor.lineHeight": "Controls the line height. \n - Use 0 to automatically compute the line height from the font size.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values.", - "editor.renderLineHighlightOnlyWhenFocus": "Controls if the editor should render the current line highlight only when the editor is focused.", - "editor.renderWhitespace3": "Render only trailing whitespace characters.", - "editor.scrollbar.horizontal": "Controls the visibility of the horizontal scrollbar.", - "editor.scrollbar.horizontal0": "The horizontal scrollbar will be visible only when necessary.", - "editor.scrollbar.horizontal1": "The horizontal scrollbar will always be visible.", - "editor.scrollbar.horizontal2": "The horizontal scrollbar will always be hidden.", - "editor.scrollbar.horizontalScrollbarSize": "The height of the horizontal scrollbar.", - "editor.scrollbar.scrollByPage": "Controls whether clicks scroll by page or jump to click position.", - "editor.scrollbar.vertical": "Controls the visibility of the vertical scrollbar.", - "editor.scrollbar.vertical0": "The vertical scrollbar will be visible only when necessary.", - "editor.scrollbar.vertical1": "The vertical scrollbar will always be visible.", - "editor.scrollbar.vertical2": "The vertical scrollbar will always be hidden.", - "editor.scrollbar.verticalScrollbarSize": "The width of the vertical scrollbar.", - "editor.stickyTabStops": "Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.", - "editor.suggest.localityBonus": "Controls whether sorting favors words that appear close to the cursor.", - "editor.suggest.preview": "Controls whether to preview the suggestion outcome in the editor.", - "editor.suggest.showDeprecated": "When enabled IntelliSense shows `deprecated`-suggestions.", - "editor.unicodeHighlight.allowedCharacters": "Defines allowed characters that are not being highlighted.", - "editor.unicodeHighlight.allowedLocales": "Unicode characters that are common in allowed locales are not being highlighted.", - "editor.unicodeHighlight.ambiguousCharacters": "Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.", - "editor.unicodeHighlight.includeComments": "Controls whether characters in comments should also be subject to unicode highlighting.", - "editor.unicodeHighlight.includeStrings": "Controls whether characters in strings should also be subject to unicode highlighting.", - "editor.unicodeHighlight.invisibleCharacters": "Controls whether characters that just reserve space or have no width at all are highlighted.", - "editor.unicodeHighlight.nonBasicASCII": "Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.", - "editor.wordBasedSuggestionsMode": "Controls from which documents word based completions are computed.", - "files.autoSave": "Controls [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors that have unsaved changes.", - "files.autoSave.afterDelay": "An editor with changes is automatically saved after the configured `#files.autoSaveDelay#`.", - "files.autoSave.off": "An editor with changes is never automatically saved.", - "files.autoSave.onFocusChange": "An editor with changes is automatically saved when the editor loses focus.", - "files.autoSave.onWindowChange": "An editor with changes is automatically saved when the window loses focus.", - "formatOnSaveTimeout": "Timeout in milliseconds after which the formatting that is run on file save is cancelled.", - "persistClosedEditors": "Controls whether to persist closed editor history for the workspace across window reloads.", - "showAllEditors": "Show All Opened Editors", - "splitHorizontal": "Split Editor Horizontal", - "splitVertical": "Split Editor Vertical", "unsavedTitle": "Unsaved – {0}" }, - "file-search": { - "toggleIgnoredFiles": " (Press {0} to show/hide ignored files)" - }, - "fileSystem": { - "fileResource": { - "overWriteBody": "Do you want to overwrite the changes made to '{0}' on the file system?" - } - }, - "filesystem": { - "copyDownloadLink": "Copy Download Link", - "fileResource": { - "binaryFileQuery": "Opening it might take some time and might make the IDE unresponsive. Do you want to open '{0}' anyway?", - "binaryTitle": "The file is either binary or uses an unsupported text encoding.", - "largeFileTitle": "The file is too large ({0}).", - "overwriteTitle": "The file '{0}' has been changed on the file system." - }, - "filesExclude": "Configure glob patterns for excluding files and folders. For example, the file Explorer decides which files and folders to show or hide based on this setting.", - "maxConcurrentUploads": "Maximum number of concurrent files to upload when uploading multiple files. 0 means all files will be uploaded concurrently.", - "maxFileSizeMB": "Controls the max file size in MB which is possible to open.", - "processedOutOf": "Processed {0} out of {1}", - "uploadFiles": "Upload Files...", - "uploadedOutOf": "Uploaded {0} out of {1}" - }, - "git": { - "addSignedOff": "Add Signed-off-by", - "added": "Added", - "amendReuseMessag": "To reuse the last commit message, press 'Enter' or 'Escape' to cancel.", - "amendRewrite": "Rewrite previous commit message. Press 'Enter' to confirm or 'Escape' to cancel.", - "checkoutCreateLocalBranchWithName": "Create a new local branch with name: {0}. Press 'Enter' to confirm or 'Escape' to cancel.", - "checkoutProvideBranchName": "Please provide a branch name. ", - "checkoutSelectRef": "Select a ref to checkout or create a new local branch:", - "cloneQuickInputLabel": "Please provide a Git repository location. Press 'Enter' to confirm or 'Escape' to cancel.", - "cloneRepository": "Clone the Git repository: {0}. Press 'Enter' to confirm or 'Escape' to cancel.", - "compareWith": "Compare With...", - "compareWithBranchOrTag": "Pick a branch or tag to compare with the currently active {0} branch:", - "conflicted": "Conflicted", - "copied": "Copied", - "dirtyDiffLinesLimit": "Do not show dirty diff decorations, if editor's line count exceeds this limit.", - "dropStashMessage": "Stash successfully removed.", - "editorDecorationsEnabled": "Show git decorations in the editor.", - "fetchPickRemote": "Pick a remote to fetch from:", - "gitDecorationsColors": "Use color decoration in the navigator.", - "mergeQuickPickPlaceholder": "Pick a branch to merge into the currently active {0} branch:", - "missingUserInfo": "Make sure you configure your 'user.name' and 'user.email' in git.", - "noPreviousCommit": "No previous commit to amend", - "noRepositoriesSelected": "No repositories were selected.", - "renamed": "Renamed", - "repositoryNotInitialized": "Repository {0} is not yet initialized.", - "stashChanges": "Stash changes. Press 'Enter' to confirm or 'Escape' to cancel.", - "stashChangesWithMessage": "Stash changes with message: {0}. Press 'Enter' to confirm or 'Escape' to cancel.", - "toggleBlameAnnotations": "Toggle Blame Annotations", - "unstaged": "Unstaged" - }, - "keybinding-schema-updater": { - "deprecation": "Use `when` clause instead." - }, - "markers": { - "clearAll": "Clear All", - "tabbarDecorationsEnabled": "Show problem decorators (diagnostic markers) in the tab bars." - }, "messages": { "collapse": "Collapse", - "expand": "Expand", - "notificationTimeout": "Informative notifications will be hidden after this timeout.", - "toggleNotifications": "Toggle Notifications" - }, - "monaco": { - "noSymbolsMatching": "No symbols matching", - "typeToSearchForSymbols": "Type to search for symbols" - }, - "navigator": { - "autoReveal": "Auto Reveal", - "refresh": "Refresh in Explorer", - "reveal": "Reveal in Explorer", - "toggleHiddenFiles": "Toggle Hidden Files" - }, - "output": { - "clearOutputChannel": "Clear Output Channel...", - "closeOutputChannel": "Close Output Channel...", - "hiddenChannels": "Hidden Channels", - "hideOutputChannel": "Hide Output Channel...", - "maxChannelHistory": "The maximum number of entries in an output channel.", - "outputChannels": "Output Channels", - "showOutputChannel": "Show Output Channel..." - }, - "plugin-ext": { - "plugins": "Plugins", - "signInAgain": "The extension '{0}' wants you to sign in again using {1}.", - "webviewTrace": "Controls communication tracing with webviews.", - "webviewWarnIfUnsecure": "Warns users that webviews are currently deployed unsecurely." - }, - "scm": { - "amend": "Amend", - "amendHeadCommit": "HEAD Commit", - "amendLastCommit": "Amend last commit", - "changeRepository": "Change Repository...", - "history": "History", - "noRepositoryFound": "No repository found", - "unamend": "Unamend", - "unamendCommit": "Unamend commit" - }, - "search-in-workspace": { - "includeIgnoredFiles": "Include Ignored Files", - "noFolderSpecified": "You have not opened or specified a folder. Only open files are currently searched.", - "resultSubset": "This is only a subset of all results. Use a more specific search term to narrow down the result list.", - "searchOnEditorModification": "Search the active editor when modified." - }, - "task": { - "attachTask": "Attach Task...", - "clearHistory": "Clear History", - "openUserTasks": "Open User Tasks" - }, - "terminal": { - "confirmClose": "Controls whether to confirm when the window closes if there are active terminal sessions.", - "confirmCloseAlways": "Always confirm if there are terminals.", - "confirmCloseChildren": "Confirm if there are any terminals that have child processes.", - "confirmCloseNever": "Never confirm.", - "enableCopy": "Enable ctrl-c (cmd-c on macOS) to copy selected text", - "enablePaste": "Enable ctrl-v (cmd-v on macOS) to paste from clipboard", - "shellArgsLinux": "The command line arguments to use when on the Linux terminal.", - "shellArgsOsx": "The command line arguments to use when on the macOS terminal.", - "shellArgsWindows": "The command line arguments to use when on the Windows terminal.", - "shellLinux": "The path of the shell that the terminal uses on Linux (default: '{0}'}).", - "shellOsx": "The path of the shell that the terminal uses on macOS (default: '{0}'}).", - "shellWindows": "The path of the shell that the terminal uses on Windows. (default: '{0}').", - "terminate": "Terminate", - "terminateActive": "Do you want to terminate the active terminal session?", - "terminateActiveMultiple": "Do you want to terminate the {0} active terminal sessions?" - }, - "webview": { - "goToReadme": "Go To README", - "messageWarning": " The {0} endpoint's host pattern has been changed to `{1}`; changing the pattern can lead to security vulnerabilities. See `{2}` for more information." + "expand": "Expand" }, "workspace": { - "closeWorkspace": "Do you really want to close the workspace?", - "compareWithEachOther": "Compare with Each Other", - "confirmDeletePermanently.description": "Failed to delete \"{0}\" using the Trash. Do you want to permanently delete instead?", - "confirmDeletePermanently.solution": "You can disable the use of Trash in the preferences.", - "confirmDeletePermanently.title": "Error deleting file", "deleteCurrentSketch": "Do you want to delete the current sketch?", - "duplicate": "Duplicate", - "failApply": "Could not apply changes to new file", - "failSaveAs": "Cannot run \"{0}\" for the current widget.", "fileNewName": "Name for new file", "invalidExtension": ".{0} is not a valid extension", "invalidFilename": "Invalid filename.", - "newFileName": "New name for file", - "noErasure": "Note: Nothing will be erased from disk", - "openRecentPlaceholder": "Type the name of the workspace you want to open", - "openRecentWorkspace": "Open Recent Workspace...", - "preserveWindow": "Enable opening workspaces in current window.", - "removeFolder": "Are you sure you want to remove the following folder from the workspace?", - "removeFolders": "Are you sure you want to remove the following folders from the workspace?", - "sketchDirectoryError": "There was an error creating the sketch directory. See the log for more details. The application will probably not work as expected.", - "supportMultiRootWorkspace": "Controls whether multi-root workspace support is enabled.", - "trustEmptyWindow": "Controls whether or not the empty workspace is trusted by default.", - "trustEnabled": "Controls whether or not workspace trust is enabled. If disabled, all workspaces are trusted.", - "trustPrompt": "Controls when the startup prompt to trust a workspace is shown.", - "trustRequest": "An extension requests workspace trust but the corresponding API is not yet fully supported. Do you want to trust this workspace?", - "untitled-cleanup": "There appear to be many untitled workspace files. Please check {0} and remove any unused files.", - "workspaceFolderAdded": "A workspace with multiple roots was created. Do you want to save your workspace configuration as a file?", - "workspaceFolderAddedTitle": "Folder added to Workspace" + "newFileName": "New name for file" } - }, - "title.matchesCountLimit": "Only the first {0} results are highlighted, but all find operations work on the entire text.", - "toggle.tabMovesFocus.off": "Pressing Tab will now insert the tab character", - "toggle.tabMovesFocus.on": "Pressing Tab will now move focus to the next focusable element", - "toggleFoldAction.label": "Toggle Fold", - "toggleHighContrast": "Toggle High Contrast Theme", - "too many characters": "Tokenization is skipped for long lines for performance reasons. This can be configured via `editor.maxTokenizationLineLength`.", - "toolbarActiveBackground": "Toolbar background when holding the mouse over actions", - "toolbarHoverBackground": "Toolbar background when hovering over actions using the mouse", - "toolbarHoverOutline": "Toolbar outline when hovering over actions using the mouse", - "tooltip.explanation": "Execute command {0}", - "transposeLetters.label": "Transpose Letters", - "treeIndentGuidesStroke": "Tree stroke color for the indentation guides.", - "trimAutoWhitespace": "Remove trailing auto inserted whitespace.", - "typedef.title": "Type Definitions", - "unFoldRecursivelyAction.label": "Unfold Recursively", - "undo": "Undo", - "unfoldAction.label": "Unfold", - "unfoldAllAction.label": "Unfold All", - "unfoldAllExcept.label": "Unfold All Regions Except Selected", - "unfoldAllMarkerRegions.label": "Unfold All Regions", - "unfoldOnClickAfterEndOfLine": "Controls whether clicking on the empty content after a folded line will unfold the line.", - "unicodeHighlight.adjustSettings": "Adjust settings", - "unicodeHighlight.allowCommonCharactersInLanguage": "Allow unicode characters that are more common in the language \"{0}\".", - "unicodeHighlight.allowedCharacters": "Defines allowed characters that are not being highlighted.", - "unicodeHighlight.allowedLocales": "Unicode characters that are common in allowed locales are not being highlighted.", - "unicodeHighlight.ambiguousCharacters": "Controls whether characters are highlighted that can be confused with basic ASCII characters, except those that are common in the current user locale.", - "unicodeHighlight.characterIsAmbiguous": "The character {0} could be confused with the character {1}, which is more common in source code.", - "unicodeHighlight.characterIsInvisible": "The character {0} is invisible.", - "unicodeHighlight.characterIsNonBasicAscii": "The character {0} is not a basic ASCII character.", - "unicodeHighlight.configureUnicodeHighlightOptions": "Configure Unicode Highlight Options", - "unicodeHighlight.disableHighlightingInComments.shortLabel": "Disable Highlight In Comments", - "unicodeHighlight.disableHighlightingInStrings.shortLabel": "Disable Highlight In Strings", - "unicodeHighlight.disableHighlightingOfAmbiguousCharacters.shortLabel": "Disable Ambiguous Highlight", - "unicodeHighlight.disableHighlightingOfInvisibleCharacters.shortLabel": "Disable Invisible Highlight", - "unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters.shortLabel": "Disable Non ASCII Highlight", - "unicodeHighlight.excludeCharFromBeingHighlighted": "Exclude {0} from being highlighted", - "unicodeHighlight.excludeInvisibleCharFromBeingHighlighted": "Exclude {0} (invisible character) from being highlighted", - "unicodeHighlight.includeComments": "Controls whether characters in comments should also be subject to unicode highlighting.", - "unicodeHighlight.includeStrings": "Controls whether characters in strings should also be subject to unicode highlighting.", - "unicodeHighlight.invisibleCharacters": "Controls whether characters that just reserve space or have no width at all are highlighted.", - "unicodeHighlight.nonBasicASCII": "Controls whether all non-basic ASCII characters are highlighted. Only characters between U+0020 and U+007E, tab, line-feed and carriage-return are considered basic ASCII.", - "unicodeHighlighting.thisDocumentHasManyAmbiguousUnicodeCharacters": "This document contains many ambiguous unicode characters", - "unicodeHighlighting.thisDocumentHasManyInvisibleUnicodeCharacters": "This document contains many invisible unicode characters", - "unicodeHighlighting.thisDocumentHasManyNonBasicAsciiUnicodeCharacters": "This document contains many non-basic ASCII unicode characters", - "unnecessaryCodeBorder": "Border color of unnecessary (unused) source code in the editor.", - "unnecessaryCodeOpacity": "Opacity of unnecessary (unused) source code in the editor. For example, \"#000000c0\" will render the code with 75% opacity. For high contrast themes, use the 'editorUnnecessaryCode.border' theme color to underline unnecessary code instead of fading it out.", - "unusualLineTerminators": "Remove unusual line terminators that might cause problems.", - "unusualLineTerminators.auto": "Unusual line terminators are automatically removed.", - "unusualLineTerminators.detail": "The file '{0}' contains one or more unusual line terminator characters, like Line Separator (LS) or Paragraph Separator (PS).\n\nIt is recommended to remove them from the file. This can be configured via `editor.unusualLineTerminators`.", - "unusualLineTerminators.fix": "Remove Unusual Line Terminators", - "unusualLineTerminators.ignore": "Ignore", - "unusualLineTerminators.message": "Detected unusual line terminators", - "unusualLineTerminators.off": "Unusual line terminators are ignored.", - "unusualLineTerminators.prompt": "Unusual line terminators prompt to be removed.", - "unusualLineTerminators.title": "Unusual Line Terminators", - "useTabStops": "Inserting and deleting whitespace follows tab stops.", - "view problem": "View Problem", - "warningBorder": "Border color of warning boxes in the editor.", - "warningIcon": "Icon shown with a warning message in the extensions editor.", - "widgetShadow": "Shadow color of widgets such as find/replace inside the editor.", - "wordBasedSuggestions": "Controls whether completions should be computed based on words in the document.", - "wordBasedSuggestionsMode": "Controls from which documents word based completions are computed.", - "wordBasedSuggestionsMode.allDocuments": "Suggest words from all open documents.", - "wordBasedSuggestionsMode.currentDocument": "Only suggest words from the active document.", - "wordBasedSuggestionsMode.matchingDocuments": "Suggest words from all open documents of the same language.", - "wordHighlight": "Background color of a symbol during read-access, like reading a variable. The color must not be opaque so as not to hide underlying decorations.", - "wordHighlight.next.label": "Go to Next Symbol Highlight", - "wordHighlight.previous.label": "Go to Previous Symbol Highlight", - "wordHighlight.trigger.label": "Trigger Symbol Highlight", - "wordHighlightBorder": "Border color of a symbol during read-access, like reading a variable.", - "wordHighlightStrong": "Background color of a symbol during write-access, like writing to a variable. The color must not be opaque so as not to hide underlying decorations.", - "wordHighlightStrongBorder": "Border color of a symbol during write-access, like writing to a variable.", - "wordSeparators": "Characters that will be used as word separators when doing word related navigations or operations.", - "wordWrap.inherit": "Lines will wrap according to the `#editor.wordWrap#` setting.", - "wordWrap.off": "Lines will never wrap.", - "wordWrap.on": "Lines will wrap at the viewport width.", - "wordsDescription": "Match Whole Word", - "wrappingIndent": "Controls the indentation of wrapped lines.", - "wrappingIndent.deepIndent": "Wrapped lines get +2 indentation toward the parent.", - "wrappingIndent.indent": "Wrapped lines get +1 indentation toward the parent.", - "wrappingIndent.none": "No indentation. Wrapped lines begin at column 1.", - "wrappingIndent.same": "Wrapped lines get the same indentation as the parent.", - "wrappingStrategy": "Controls the algorithm that computes wrapping points.", - "wrappingStrategy.advanced": "Delegates wrapping points computation to the browser. This is a slow algorithm, that might cause freezes for large files, but it works correctly in all cases.", - "wrappingStrategy.simple": "Assumes that all characters are of the same width. This is a fast algorithm that works correctly for monospace fonts and certain scripts (like Latin characters) where glyphs are of equal width." + } } From c81d1c52e4e8571610b30461750f34d4183a181e Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 24 May 2022 17:52:17 +0200 Subject: [PATCH 27/45] removed native grpc dependencies. bumped the grpc-js version. Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 4 +- yarn.lock | 130 ++--------------------------- 2 files changed, 8 insertions(+), 126 deletions(-) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index 9b7be28b2..d99fc64c6 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -21,7 +21,7 @@ "test:watch": "mocha --watch --watch-files lib \"./lib/test/**/*.test.js\"" }, "dependencies": { - "@grpc/grpc-js": "^1.3.7", + "@grpc/grpc-js": "^1.6.7", "@theia/application-package": "1.25.0", "@theia/core": "1.25.0", "@theia/editor": "1.25.0", @@ -70,8 +70,6 @@ "electron-updater": "^4.6.5", "fast-safe-stringify": "^2.1.1", "glob": "^7.1.6", - "google-protobuf": "^3.11.4", - "grpc": "^1.24.11", "hash.js": "^1.1.7", "is-valid-path": "^0.1.1", "js-yaml": "^3.13.1", diff --git a/yarn.lock b/yarn.lock index cf1708f2c..def666615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1105,7 +1105,7 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@grpc/grpc-js@^1.3.7": +"@grpc/grpc-js@^1.6.7": version "1.6.7" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.6.7.tgz#4c4fa998ff719fe859ac19fe977fdef097bb99aa" integrity sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw== @@ -1870,7 +1870,7 @@ dependencies: cross-spawn "^7.0.1" -"@mapbox/node-pre-gyp@^1.0.4", "@mapbox/node-pre-gyp@^1.0.5": +"@mapbox/node-pre-gyp@^1.0.5": version "1.0.9" resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz#09a8781a3a036151cdebbe8719d6f8b25d4058bc" integrity sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw== @@ -2981,14 +2981,6 @@ dependencies: "@types/node" "*" -"@types/bytebuffer@^5.0.40": - version "5.0.43" - resolved "https://registry.yarnpkg.com/@types/bytebuffer/-/bytebuffer-5.0.43.tgz#b5259fca1412106bcee0cabfbf7c104846d06738" - integrity sha512-vQnTYvy4LpSojHjKdmg4nXFI1BAiYPvZ/k3ouczZAQnbDprk1xqxJiFmFHyy8y6MuUq3slz5erNMtn6n87uVKw== - dependencies: - "@types/long" "*" - "@types/node" "*" - "@types/cacheable-request@^6.0.1": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" @@ -3221,7 +3213,7 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== -"@types/long@*", "@types/long@^4.0.1": +"@types/long@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== @@ -4422,14 +4414,6 @@ asap@^2.0.0: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== -ascli@~1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ascli/-/ascli-1.0.1.tgz#bcfa5974a62f18e81cabaeb49732ab4a88f906bc" - integrity sha512-JGQaNxpaCJz9Bd1JvVaFIHuWn9S+l3xhN17R0V/vmUDiGE0QngNMXhjlqpwqV+91plWz9Fg+Lt28Lj7p5vjs8A== - dependencies: - colour "~0.7.1" - optjs "~3.2.2" - asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -4913,13 +4897,6 @@ byte-size@^5.0.1: resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191" integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== -bytebuffer@~5: - version "5.0.1" - resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd" - integrity sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ== - dependencies: - long "~3" - bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -5121,7 +5098,7 @@ camelcase-keys@^6.2.2: map-obj "^4.0.0" quick-lru "^4.0.1" -camelcase@^2.0.0, camelcase@^2.0.1: +camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw== @@ -5313,15 +5290,6 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== -cliui@^3.0.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" @@ -5460,11 +5428,6 @@ colorette@^2.0.16: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== -colour@~0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" - integrity sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g= - columnify@^1.5.4: version "1.6.0" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" @@ -7860,7 +7823,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: +glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -7967,11 +7930,6 @@ google-protobuf@3.12.4: resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.4.tgz#fd89b7e5052cdb35a80f9b455612851d542a5c9f" integrity sha512-ItTn8YepDQMHEMHloUPH+FDaTPiHTnbsMvP50aXfbI65IK3AA5+wXlHSygJH8xz+h1g4gu7V+CK5X1/SaGITsA== -google-protobuf@^3.11.4: - version "3.20.1" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.20.1.tgz#1b255c2b59bcda7c399df46c65206aa3c7a0ce8b" - integrity sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw== - got@^11.7.0: version "11.8.3" resolved "https://registry.yarnpkg.com/got/-/got-11.8.3.tgz#f496c8fdda5d729a90b4905d2b07dbd148170770" @@ -8046,18 +8004,6 @@ grpc-tools@^1.9.0: dependencies: "@mapbox/node-pre-gyp" "^1.0.5" -grpc@^1.24.11: - version "1.24.11" - resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.24.11.tgz#7039da9f6f22ce35168535a6d5dda618398a5966" - integrity sha512-8/AQdFCzCeCDWW3SoaMNp6ccbRvTQEH1O1u1uFtt29eWsg5gSZCJ3m6fbkduEIh3smY7WAPP+LgVJ5n3nZRxcA== - dependencies: - "@mapbox/node-pre-gyp" "^1.0.4" - "@types/bytebuffer" "^5.0.40" - lodash.camelcase "^4.3.0" - lodash.clone "^4.5.0" - nan "^2.13.2" - protobufjs "^5.0.3" - grpc_tools_node_protoc_ts@^4.1.0: version "4.1.5" resolved "https://registry.yarnpkg.com/grpc_tools_node_protoc_ts/-/grpc_tools_node_protoc_ts-4.1.5.tgz#ad540a51867ff407196538d2d6370b27d6d3cfc8" @@ -8684,11 +8630,6 @@ inversify@^5.1.1: resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.1.1.tgz#6fbd668c591337404e005a1946bfe0d802c08730" integrity sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ== -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" @@ -9472,13 +9413,6 @@ lazy-val@^1.0.5: resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d" integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q== -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -9693,11 +9627,6 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= -lodash.clone@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" - integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= - lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -9837,11 +9766,6 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== -long@~3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" - integrity sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s= - loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -10810,7 +10734,7 @@ mz@^2.5.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.13.2, nan@^2.14.0: +nan@^2.14.0: version "2.15.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== @@ -11416,11 +11340,6 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -optjs@~3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/optjs/-/optjs-3.2.2.tgz#69a6ce89c442a44403141ad2f9b370bd5bb6f4ee" - integrity sha1-aabOicRCpEQDFBrS+bNwvVu29O4= - ora@^5.1.0: version "5.4.1" resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" @@ -11441,13 +11360,6 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - os-locale@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -12132,16 +12044,6 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -protobufjs@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-5.0.3.tgz#e4dfe9fb67c90b2630d15868249bcc4961467a17" - integrity sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA== - dependencies: - ascli "~1" - bytebuffer "~5" - glob "^7.0.5" - yargs "^3.10.0" - protobufjs@^6.10.0: version "6.11.2" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b" @@ -15277,11 +15179,6 @@ winchan@^0.2.2: resolved "https://registry.yarnpkg.com/winchan/-/winchan-0.2.2.tgz#6766917b88e5e1cb75f455ffc7cc13f51e5c834e" integrity sha512-pvN+IFAbRP74n/6mc6phNyCH8oVkzXsto4KCHPJ2AScniAnA1AmeLI03I2BzjePpaClGSI4GUMowzsD3qz5PRQ== -window-size@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" - integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= - windows-release@^3.1.0: version "3.3.3" resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" @@ -15460,7 +15357,7 @@ xterm@^4.16.0: resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.18.0.tgz#a1f6ab2c330c3918fb094ae5f4c2562987398ea1" integrity sha512-JQoc1S0dti6SQfI0bK1AZvGnAxH4MVw45ZPFSO6FHTInAiau3Ix77fSxNx3mX4eh9OL4AYa8+4C8f5UvnSfppQ== -y18n@^3.2.0, y18n@^3.2.1: +y18n@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== @@ -15639,19 +15536,6 @@ yargs@^17.0.1: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^3.10.0: - version "3.32.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" - integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= - dependencies: - camelcase "^2.0.1" - cliui "^3.0.3" - decamelize "^1.1.1" - os-locale "^1.4.0" - string-width "^1.0.1" - window-size "^0.1.4" - y18n "^3.2.0" - yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From 71bbeda48250e18121329f908f0186042687b083 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 25 May 2022 13:24:07 +0200 Subject: [PATCH 28/45] Can start the IDE with content tracing. Signed-off-by: Akos Kitta --- .gitignore | 2 + .vscode/launch.json | 2 +- .../theia/electron-main-application.ts | 85 ++++++++++++++++++- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index fdab6fb0e..5d9bf1ea6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ yarn*.log plugins # the config files for the CLI arduino-ide-extension/data/cli/config +# content trace files for electron +electron-app/traces diff --git a/.vscode/launch.json b/.vscode/launch.json index 3ab3ee582..c50d311c7 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,7 +21,7 @@ "--plugins=local-dir:../plugins", "--hosted-plugin-inspect=9339", "--nosplash", - "--open-devtools" + "--content-trace" ], "env": { "NODE_ENV": "development" diff --git a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts index 009045a1a..1aa11ea31 100644 --- a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts +++ b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts @@ -1,5 +1,13 @@ import { inject, injectable } from '@theia/core/shared/inversify'; -import { app, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, screen, Event as ElectronEvent } from '@theia/core/electron-shared/electron'; +import { + app, + BrowserWindow, + BrowserWindowConstructorOptions, + contentTracing, + ipcMain, + screen, + Event as ElectronEvent, +} from '@theia/core/electron-shared/electron'; import { fork } from 'child_process'; import { AddressInfo } from 'net'; import { join, dirname } from 'path'; @@ -46,7 +54,15 @@ const APP_STARTED_WITH_NOSPLASH = * If the app is started with `--open-devtools` argument, the `Dev Tools` will be opened. */ const APP_STARTED_WITH_DEV_TOOLS = - typeof process !== 'undefined' && process.argv.indexOf('--open-devtools') !== -1; + typeof process !== 'undefined' && + process.argv.indexOf('--open-devtools') !== -1; + +/** + * If the app is started with `--content-trace` argument, the `Dev Tools` will be opened and content tracing will start. + */ +const APP_STARTED_WITH_CONTENT_TRACE = + typeof process !== 'undefined' && + process.argv.indexOf('--content-trace') !== -1; @injectable() export class ElectronMainApplication extends TheiaElectronMainApplication { @@ -62,7 +78,68 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { // Regression in Theia: https://github.com/eclipse-theia/theia/issues/8701 app.on('ready', () => app.setName(config.applicationName)); this.attachFileAssociations(); - return super.start(config); + this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native'; + this._config = config; + this.hookApplicationEvents(); + const [port] = await Promise.all([this.startBackend(), app.whenReady()]); + this.startContentTracing(); + this._backendPort.resolve(port); + await Promise.all([ + this.attachElectronSecurityToken(port), + this.startContributions(), + ]); + return this.launch({ + secondInstance: false, + argv: this.processArgv.getProcessArgvWithoutBin(process.argv), + cwd: process.cwd(), + }); + } + + private startContentTracing(): void { + if (!APP_STARTED_WITH_CONTENT_TRACE) { + return; + } + if (!app.isReady()) { + throw new Error( + 'Cannot start content tracing when the electron app is not ready.' + ); + } + const defaultTraceCategories: Readonly> = [ + '-*', + 'devtools.timeline', + 'disabled-by-default-devtools.timeline', + 'disabled-by-default-devtools.timeline.frame', + 'toplevel', + 'blink.console', + 'disabled-by-default-devtools.timeline.stack', + 'disabled-by-default-v8.cpu_profile', + 'disabled-by-default-v8.cpu_profiler', + 'disabled-by-default-v8.cpu_profiler.hires', + ]; + const traceOptions = { + categoryFilter: defaultTraceCategories.join(','), + traceOptions: 'record-until-full', + options: 'sampling-frequency=10000', + }; + (async () => { + const appPath = app.getAppPath(); + let traceFile: string | undefined; + if (appPath) { + const tracesPath = join(appPath, 'traces'); + await fs.promises.mkdir(tracesPath, { recursive: true }); + traceFile = join(tracesPath, `trace-${new Date().toISOString()}.trace`); + } + console.log('>>> Content tracing has started...'); + await contentTracing.startRecording(traceOptions); + await new Promise((resolve) => setTimeout(resolve, 10_000)); + contentTracing + .stopRecording(traceFile) + .then((out) => + console.log( + `<<< Content tracing has finished. The trace data was written to: ${out}.` + ) + ); + })(); } attachFileAssociations() { @@ -164,7 +241,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { return super.avoidOverlap(options); } - protected override getTitleBarStyle(): 'native' | 'custom' { + protected override getTitleBarStyle(config: FrontendApplicationConfig): 'native' | 'custom' { return 'native'; } From ad76045225b972a68c1609bb13866b36cfe8715c Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 25 May 2022 15:38:20 +0200 Subject: [PATCH 29/45] Skip loading extensions for the Theia about dialog It's unused in IDE2. Signed-off-by: Akos Kitta --- .../src/browser/arduino-ide-frontend-module.ts | 9 ++++++++- .../src/browser/theia/core/about-dialog.ts | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 arduino-ide-extension/src/browser/theia/core/about-dialog.ts diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 5a67e3a74..2e52f6940 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -277,6 +277,8 @@ import { EditorNavigationContribution } from './theia/editor/editor-navigation-c import { EditorNavigationContribution as TheiaEditorNavigationContribution } from '@theia/editor/lib/browser/editor-navigation-contribution'; import { PreferenceTreeGenerator } from './theia/preferences/preference-tree-generator'; import { PreferenceTreeGenerator as TheiaPreferenceTreeGenerator } from '@theia/preferences/lib/browser/util/preference-tree-generator'; +import { AboutDialog } from './theia/core/about-dialog'; +import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog'; MonacoThemingService.register({ id: 'arduino-theme', @@ -687,9 +689,14 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { EditorNavigationContribution ); - bind(PreferenceTreeGenerator).toSelf().inSingletonScope() + // IDE2 does not use the Theia preferences widget, no need to create and sync the underlying tree model. + bind(PreferenceTreeGenerator).toSelf().inSingletonScope(); rebind(TheiaPreferenceTreeGenerator).toService(PreferenceTreeGenerator); + // IDE2 has a custom about dialog, so there is no need to load the Theia extensions on FE load + bind(AboutDialog).toSelf().inSingletonScope(); + rebind(TheiaAboutDialog).toService(AboutDialog); + // To avoid running `Save All` when there are no dirty editors before starting the debug session. bind(DebugSessionManager).toSelf().inSingletonScope(); rebind(TheiaDebugSessionManager).toService(DebugSessionManager); diff --git a/arduino-ide-extension/src/browser/theia/core/about-dialog.ts b/arduino-ide-extension/src/browser/theia/core/about-dialog.ts new file mode 100644 index 000000000..3e89c5105 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/core/about-dialog.ts @@ -0,0 +1,10 @@ +import { AboutDialog as TheiaAboutDialog } from '@theia/core/lib/browser/about-dialog'; +import { duration } from '../../../common/decorators'; + +export class AboutDialog extends TheiaAboutDialog { + @duration({ name: 'theia-about#init' }) + protected override async init(): Promise { + // NOOP + // IDE2 has a custom about dialog, so it does not make sense to collect Theia extensions at startup time. + } +} From 47620ef0eb4b67774bfa0e780661558eabf28b2f Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 25 May 2022 15:39:04 +0200 Subject: [PATCH 30/45] Defer running the FW updates. Signed-off-by: Akos Kitta --- .../dialogs/firmware-uploader/firmware-uploader-dialog.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx b/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx index 27a3484dd..dd966422e 100644 --- a/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx +++ b/arduino-ide-extension/src/browser/dialogs/firmware-uploader/firmware-uploader-dialog.tsx @@ -15,6 +15,7 @@ import { } from '../../../common/protocol/arduino-firmware-uploader'; import { FirmwareUploaderComponent } from './firmware-uploader-component'; import { UploadFirmware } from '../../contributions/upload-firmware'; +import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; @injectable() export class UploadFirmwareDialogWidget extends ReactWidget { @@ -24,6 +25,9 @@ export class UploadFirmwareDialogWidget extends ReactWidget { @inject(ArduinoFirmwareUploader) protected readonly arduinoFirmwareUploader: ArduinoFirmwareUploader; + @inject(FrontendApplicationStateService) + private readonly appStatusService: FrontendApplicationStateService; + protected updatableFqbns: string[] = []; protected availableBoards: AvailableBoard[] = []; protected isOpen = new Object(); @@ -38,7 +42,8 @@ export class UploadFirmwareDialogWidget extends ReactWidget { @postConstruct() protected init(): void { - this.arduinoFirmwareUploader.updatableBoards().then((fqbns) => { + this.appStatusService.reachedState('ready').then(async () => { + const fqbns = await this.arduinoFirmwareUploader.updatableBoards(); this.updatableFqbns = fqbns; this.update(); }); From bc3aee6aedd0df6a257ba4e7e21fe75dbab99d0e Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 25 May 2022 15:40:54 +0200 Subject: [PATCH 31/45] Do not require the current window on IDE2 start. It's expensive and sync. Signed-off-by: Akos Kitta --- .../theia/core/electron-menu-contribution.ts | 93 ++++++++++++++++++- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts index a698fff51..934f286fe 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts @@ -8,7 +8,13 @@ import { } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution'; import { MainMenuManager } from '../../../common/main-menu-manager'; import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; -import { FrontendApplication } from '@theia/core/lib/browser'; +import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; +import { ZoomLevel } from '@theia/core/lib/electron-browser/window/electron-window-preferences'; +import { PreferenceScope } from '@theia/core/lib/browser/preferences/preference-scope'; +import { + getCurrentWindow, + getCurrentWebContents, +} from '@theia/core/electron-shared/@electron/remote'; @injectable() export class ElectronMenuContribution @@ -37,15 +43,19 @@ export class ElectronMenuContribution } update(): void { - (this as any).setMenu(); // if (this.appReady) { + (this as any).setMenu(); // } else { // this.updateWhenReady = true; // } } + override handleTitleBarStyling(): void { + // NOOP + } + override registerCommands(registry: CommandRegistry): void { - super.registerCommands(registry); + this.theiaRegisterCommands(registry); registry.unregisterCommand(ElectronCommands.CLOSE_WINDOW); } @@ -60,4 +70,81 @@ export class ElectronMenuContribution registry.unregisterKeybinding(ElectronCommands.ZOOM_IN.id); registry.unregisterKeybinding(ElectronCommands.ZOOM_OUT.id); } + + // Copied from Theia: https://github.com/eclipse-theia/theia/blob/9ec8835cf35d5a46101a62ae93285aeb37a2f382/packages/core/src/electron-browser/menu/electron-menu-contribution.ts#L260-L314 + // Unlike the Theia implementation, this does not require synchronously the browser window, but use a function only when the command handler executes. + private theiaRegisterCommands(registry: CommandRegistry): void { + const currentWindow = () => getCurrentWindow(); + + registry.registerCommand(ElectronCommands.TOGGLE_DEVELOPER_TOOLS, { + execute: () => { + const webContent = getCurrentWebContents(); + if (!webContent.isDevToolsOpened()) { + webContent.openDevTools(); + } else { + webContent.closeDevTools(); + } + }, + }); + + registry.registerCommand(ElectronCommands.RELOAD, { + execute: () => this.windowService.reload(), + }); + registry.registerCommand(ElectronCommands.CLOSE_WINDOW, { + execute: () => currentWindow().close(), + }); + + registry.registerCommand(ElectronCommands.ZOOM_IN, { + execute: () => { + const webContents = currentWindow().webContents; + // When starting at a level that is not a multiple of 0.5, increment by at most 0.5 to reach the next highest multiple of 0.5. + let zoomLevel = + Math.floor(webContents.zoomLevel / ZoomLevel.VARIATION) * + ZoomLevel.VARIATION + + ZoomLevel.VARIATION; + if (zoomLevel > ZoomLevel.MAX) { + zoomLevel = ZoomLevel.MAX; + return; + } + this.preferenceService.set( + 'window.zoomLevel', + zoomLevel, + PreferenceScope.User + ); + }, + }); + registry.registerCommand(ElectronCommands.ZOOM_OUT, { + execute: () => { + const webContents = currentWindow().webContents; + // When starting at a level that is not a multiple of 0.5, decrement by at most 0.5 to reach the next lowest multiple of 0.5. + let zoomLevel = + Math.ceil(webContents.zoomLevel / ZoomLevel.VARIATION) * + ZoomLevel.VARIATION - + ZoomLevel.VARIATION; + if (zoomLevel < ZoomLevel.MIN) { + zoomLevel = ZoomLevel.MIN; + return; + } + this.preferenceService.set( + 'window.zoomLevel', + zoomLevel, + PreferenceScope.User + ); + }, + }); + registry.registerCommand(ElectronCommands.RESET_ZOOM, { + execute: () => + this.preferenceService.set( + 'window.zoomLevel', + ZoomLevel.DEFAULT, + PreferenceScope.User + ), + }); + registry.registerCommand(ElectronCommands.TOGGLE_FULL_SCREEN, { + isEnabled: () => currentWindow().isFullScreenable(), + isVisible: () => currentWindow().isFullScreenable(), + execute: () => + currentWindow().setFullScreen(!currentWindow().isFullScreen()), + }); + } } From 313c96c92891e4a295c3f714a629255d081786fb Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 25 May 2022 16:09:31 +0200 Subject: [PATCH 32/45] Do not explicitly initialize the layout on start. It should be handled by the layout restorer. Signed-off-by: Akos Kitta --- .../browser/arduino-frontend-contribution.tsx | 125 ++++++------------ 1 file changed, 43 insertions(+), 82 deletions(-) diff --git a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx index 75a5f0a4d..313eaf414 100644 --- a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx +++ b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx @@ -1,4 +1,8 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import * as React from '@theia/core/shared/react'; import * as remote from '@theia/core/electron-shared/@electron/remote'; import { @@ -45,19 +49,13 @@ import { EditorManager, EditorOpenerOptions, } from '@theia/editor/lib/browser'; -import { ProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution'; import { MonacoMenus } from '@theia/monaco/lib/browser/monaco-menu'; -import { FileNavigatorCommands, FileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution'; -import { OutlineViewContribution } from '@theia/outline-view/lib/browser/outline-view-contribution'; -import { OutputContribution } from '@theia/output/lib/browser/output-contribution'; -import { ScmContribution } from '@theia/scm/lib/browser/scm-contribution'; -import { SearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution'; +import { FileNavigatorCommands } from '@theia/navigator/lib/browser/navigator-contribution'; import { TerminalMenus } from '@theia/terminal/lib/browser/terminal-frontend-contribution'; import { HostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin'; import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { FileChangeType } from '@theia/filesystem/lib/browser'; import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; -import { ConfigService } from '../common/protocol/config-service'; import { ArduinoCommands } from './arduino-commands'; import { BoardsConfig } from './boards/boards-config'; import { BoardsConfigDialog } from './boards/boards-config-dialog'; @@ -70,7 +68,6 @@ import { ArduinoToolbar } from './toolbar/arduino-toolbar'; import { ArduinoPreferences } from './arduino-preferences'; import { SketchesServiceClientImpl } from '../common/protocol/sketches-service-client-impl'; import { SaveAsSketch } from './contributions/save-as-sketch'; -import { SketchbookWidgetContribution } from './widgets/sketchbook/sketchbook-widget-contribution'; import { IDEUpdaterDialog } from './dialogs/ide-updater/ide-updater-dialog'; import { IDEUpdater } from '../common/protocol/ide-updater'; import { FileSystemFrontendContribution } from '@theia/filesystem/lib/browser/filesystem-frontend-contribution'; @@ -85,96 +82,73 @@ export class ArduinoFrontendContribution TabBarToolbarContribution, CommandContribution, MenuContribution, - ColorContribution { + ColorContribution +{ @inject(ILogger) - protected logger: ILogger; + private readonly logger: ILogger; @inject(MessageService) - protected readonly messageService: MessageService; + private readonly messageService: MessageService; @inject(BoardsService) - protected readonly boardsService: BoardsService; + private readonly boardsService: BoardsService; @inject(LibraryService) - protected readonly libraryService: LibraryService; + private readonly libraryService: LibraryService; @inject(BoardsServiceProvider) - protected readonly boardsServiceClientImpl: BoardsServiceProvider; + private readonly boardsServiceClientImpl: BoardsServiceProvider; @inject(EditorManager) - protected readonly editorManager: EditorManager; + private readonly editorManager: EditorManager; @inject(FileService) - protected readonly fileService: FileService; + private readonly fileService: FileService; @inject(SketchesService) - protected readonly sketchService: SketchesService; + private readonly sketchService: SketchesService; @inject(BoardsConfigDialog) - protected readonly boardsConfigDialog: BoardsConfigDialog; + private readonly boardsConfigDialog: BoardsConfigDialog; @inject(CommandRegistry) - protected readonly commandRegistry: CommandRegistry; + private readonly commandRegistry: CommandRegistry; @inject(StatusBar) - protected readonly statusBar: StatusBar; - - @inject(FileNavigatorContribution) - protected readonly fileNavigatorContributions: FileNavigatorContribution; - - @inject(OutputContribution) - protected readonly outputContribution: OutputContribution; - - @inject(OutlineViewContribution) - protected readonly outlineContribution: OutlineViewContribution; - - @inject(ProblemContribution) - protected readonly problemContribution: ProblemContribution; - - @inject(ScmContribution) - protected readonly scmContribution: ScmContribution; - - @inject(SearchInWorkspaceFrontendContribution) - protected readonly siwContribution: SearchInWorkspaceFrontendContribution; - - @inject(SketchbookWidgetContribution) - protected readonly sketchbookWidgetContribution: SketchbookWidgetContribution; + private readonly statusBar: StatusBar; @inject(EditorMode) - protected readonly editorMode: EditorMode; - - @inject(ConfigService) - protected readonly configService: ConfigService; + private readonly editorMode: EditorMode; @inject(HostedPluginSupport) - protected hostedPluginSupport: HostedPluginSupport; + private readonly hostedPluginSupport: HostedPluginSupport; @inject(ExecutableService) - protected executableService: ExecutableService; + private readonly executableService: ExecutableService; @inject(ArduinoPreferences) - protected readonly arduinoPreferences: ArduinoPreferences; + private readonly arduinoPreferences: ArduinoPreferences; @inject(SketchesServiceClientImpl) - protected readonly sketchServiceClient: SketchesServiceClientImpl; + private readonly sketchServiceClient: SketchesServiceClientImpl; @inject(FrontendApplicationStateService) - protected readonly appStateService: FrontendApplicationStateService; + private readonly appStateService: FrontendApplicationStateService; @inject(LocalStorageService) - protected readonly localStorageService: LocalStorageService; + private readonly localStorageService: LocalStorageService; @inject(FileSystemFrontendContribution) - protected readonly fileSystemFrontendContribution: FileSystemFrontendContribution; + private readonly fileSystemFrontendContribution: FileSystemFrontendContribution; @inject(IDEUpdater) - protected readonly updater: IDEUpdater; + private readonly updater: IDEUpdater; @inject(IDEUpdaterDialog) - protected readonly updaterDialog: IDEUpdaterDialog; + private readonly updaterDialog: IDEUpdaterDialog; @inject(ArduinoDaemon) - protected readonly daemon: ArduinoDaemon; + private readonly daemon: ArduinoDaemon; protected invalidConfigPopup: | Promise @@ -271,21 +245,6 @@ export class ArduinoFrontendContribution } async onStart(app: FrontendApplication): Promise { - // Initialize all `pro-mode` widgets. This is a NOOP if in normal mode. - for (const viewContribution of [ - this.fileNavigatorContributions, - this.outputContribution, - this.outlineContribution, - this.problemContribution, - this.scmContribution, - this.siwContribution, - this.sketchbookWidgetContribution, - ] as Array) { - if (viewContribution.initializeLayout) { - viewContribution.initializeLayout(app); - } - } - this.updater .init( this.arduinoPreferences.get('arduino.ide.updateChannel'), @@ -349,16 +308,18 @@ export class ArduinoFrontendContribution app.shell.leftPanelHandler.removeBottomMenu('settings-menu'); - this.fileSystemFrontendContribution.onDidChangeEditorFile(e => { - if (e.type === FileChangeType.DELETED) { - const editorWidget = e.editor; - if (SaveableWidget.is(editorWidget)) { - editorWidget.closeWithoutSaving(); - } else { - editorWidget.close(); + this.fileSystemFrontendContribution.onDidChangeEditorFile( + ({ type, editor }) => { + if (type === FileChangeType.DELETED) { + const editorWidget = editor; + if (SaveableWidget.is(editorWidget)) { + editorWidget.closeWithoutSaving(); + } else { + editorWidget.close(); + } } } - }); + ); } onStop(): void { @@ -501,13 +462,13 @@ export class ArduinoFrontendContribution EditorCommands.SPLIT_EDITOR_UP, EditorCommands.SPLIT_EDITOR_VERTICAL, EditorCommands.SPLIT_EDITOR_HORIZONTAL, - FileNavigatorCommands.REVEAL_IN_NAVIGATOR + FileNavigatorCommands.REVEAL_IN_NAVIGATOR, ]) { registry.unregisterCommand(command); } } - registerMenus(registry: MenuModelRegistry) { + registerMenus(registry: MenuModelRegistry): void { const menuId = (menuPath: string[]): string => { const index = menuPath.length - 1; const menuId = menuPath[index]; @@ -576,7 +537,7 @@ export class ArduinoFrontendContribution uri: string, forceOpen = false, options?: EditorOpenerOptions | undefined - ): Promise { + ): Promise { const widget = this.editorManager.all.find( (widget) => widget.editor.uri.toString() === uri ); From 68afacf726be333cd04777e14a2dc13450e5880b Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 09:11:24 +0200 Subject: [PATCH 33/45] Added missing protobuf dep. Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index d99fc64c6..b9b7304a0 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -70,6 +70,7 @@ "electron-updater": "^4.6.5", "fast-safe-stringify": "^2.1.1", "glob": "^7.1.6", + "google-protobuf": "^3.20.1", "hash.js": "^1.1.7", "is-valid-path": "^0.1.1", "js-yaml": "^3.13.1", diff --git a/yarn.lock b/yarn.lock index def666615..d9c93cb5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7930,6 +7930,11 @@ google-protobuf@3.12.4: resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.4.tgz#fd89b7e5052cdb35a80f9b455612851d542a5c9f" integrity sha512-ItTn8YepDQMHEMHloUPH+FDaTPiHTnbsMvP50aXfbI65IK3AA5+wXlHSygJH8xz+h1g4gu7V+CK5X1/SaGITsA== +google-protobuf@^3.20.1: + version "3.20.1" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.20.1.tgz#1b255c2b59bcda7c399df46c65206aa3c7a0ce8b" + integrity sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw== + got@^11.7.0: version "11.8.3" resolved "https://registry.yarnpkg.com/got/-/got-11.8.3.tgz#f496c8fdda5d729a90b4905d2b07dbd148170770" From c7f2f4f0da0419e1f52b133be4d0ad95865b6bcd Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 14:27:00 +0200 Subject: [PATCH 34/45] asynchronous core and lib index update. Signed-off-by: Akos Kitta --- .../src/node/core-client-provider.ts | 108 +++++++++++++++--- 1 file changed, 91 insertions(+), 17 deletions(-) diff --git a/arduino-ide-extension/src/node/core-client-provider.ts b/arduino-ide-extension/src/node/core-client-provider.ts index 73922d9ce..4b2fcfb14 100644 --- a/arduino-ide-extension/src/node/core-client-provider.ts +++ b/arduino-ide-extension/src/node/core-client-provider.ts @@ -21,6 +21,7 @@ import { import * as commandsGrpcPb from './cli-protocol/cc/arduino/cli/commands/v1/commands_grpc_pb'; import { NotificationServiceServer } from '../common/protocol'; import { Deferred } from '@theia/core/lib/common/promise-util'; +import { Status as RpcStatus } from './cli-protocol/google/rpc/status_pb'; @injectable() export class CoreClientProvider extends GrpcClientProvider { @@ -66,23 +67,41 @@ export class CoreClientProvider extends GrpcClientProvider { + protected override init(): void { this.daemon.getPort().then(async (port) => { // First create the client and the instance synchronously // and notify client is ready. // TODO: Creation failure should probably be handled here - await this.reconcileClient(port).then(() => { - this._created.resolve(); - }); + await this.reconcileClient(port); // create instance + this._created.resolve(); + + // Normal startup workflow: + // 1. create instance, + // 2. init instance, + // 3. update indexes asynchronously. - // If client has been created correctly update indexes and initialize - // its instance by loading platforms and cores. + // First startup workflow: + // 1. create instance, + // 2. update indexes and wait, + // 3. init instance. if (this._client && !(this._client instanceof Error)) { - await this.updateIndexes(this._client) - .then(this.initInstance) - .then(() => { + try { + await this.initInstance(this._client); + this._initialized.resolve(); + this.updateIndex(this._client); // Update the indexes asynchronously + } catch (error: unknown) { + if ( + this.isPackageIndexMissingError(error) || + this.isDiscoveryNotFoundError(error) + ) { + await this.updateIndexes(this._client); + await this.initInstance(this._client); + console.log('fooo'); this._initialized.resolve(); - }); + } else { + throw error; + } + } } }); @@ -95,6 +114,41 @@ export class CoreClientProvider extends GrpcClientProvider + message.includes('loading json index file'); + // https://github.com/arduino/arduino-cli/blob/f0245bc2da6a56fccea7b2c9ea09e85fdcc52cb8/arduino/cores/packagemanager/package_manager.go#L247 + return this.isRpcStatusError(error, assert); + } + + private isDiscoveryNotFoundError(error: unknown): boolean { + const assert = (message: string) => + message.includes('discovery') && + (message.includes('not found') || message.includes('not installed')); + // https://github.com/arduino/arduino-cli/blob/f0245bc2da6a56fccea7b2c9ea09e85fdcc52cb8/arduino/cores/packagemanager/loader.go#L740 + // https://github.com/arduino/arduino-cli/blob/f0245bc2da6a56fccea7b2c9ea09e85fdcc52cb8/arduino/cores/packagemanager/loader.go#L744 + return this.isRpcStatusError(error, assert); + } + + private isCancelError(error: unknown): boolean { + return ( + error instanceof Error && + error.message.toLocaleLowerCase().includes('cancelled on client') + ); + } + + // Final error codes are not yet defined by the CLI. Hence, we do string match in the error message. + private isRpcStatusError( + error: unknown, + assert: (message: string) => boolean + ) { + if (error instanceof RpcStatus) { + const { message } = RpcStatus.toObject(false, error); + return assert(message.toLocaleLowerCase()); + } + return false; + } + protected async createClient( port: string | number ): Promise { @@ -136,8 +190,9 @@ export class CoreClientProvider extends GrpcClientProvider { const initReq = new InitRequest(); initReq.setInstance(instance); - await new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { const stream = client.init(initReq); + const errorStatus: RpcStatus[] = []; stream.on('data', (res: InitResponse) => { const progress = res.getInitProgress(); if (progress) { @@ -153,13 +208,30 @@ export class CoreClientProvider extends GrpcClientProvider { + // on any error during the init request, the request is canceled. + // on cancel, the IDE2 ignores the cancel error and rejects with the original one. + reject( + this.isCancelError(error) && errorStatus.length + ? errorStatus[0] + : error + ); + }); + stream.on('end', () => { + if (errorStatus.length) { + reject(errorStatus); + } else { + resolve(); } }); - stream.on('error', (err) => reject(err)); - stream.on('end', resolve); }); } @@ -233,7 +305,9 @@ export class CoreClientProvider extends GrpcClientProvider((resolve, reject) => { - resp.on('error', reject); + resp.on('error', (error) => { + reject(error); + }); resp.on('end', resolve); }); } From e27b9f12d2f30f07880abefe79ff6e7b8d09764c Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 14:37:04 +0200 Subject: [PATCH 35/45] :lipstick: improved dev comments. Signed-off-by: Akos Kitta --- .../src/node/core-client-provider.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/arduino-ide-extension/src/node/core-client-provider.ts b/arduino-ide-extension/src/node/core-client-provider.ts index 4b2fcfb14..f64de1b5d 100644 --- a/arduino-ide-extension/src/node/core-client-provider.ts +++ b/arduino-ide-extension/src/node/core-client-provider.ts @@ -137,7 +137,7 @@ export class CoreClientProvider extends GrpcClientProvider boolean @@ -212,26 +212,23 @@ export class CoreClientProvider extends GrpcClientProvider { - // on any error during the init request, the request is canceled. - // on cancel, the IDE2 ignores the cancel error and rejects with the original one. + // On any error during the init request, the request is canceled. + // On cancel, the IDE2 ignores the cancel error and rejects with the original one. reject( this.isCancelError(error) && errorStatus.length ? errorStatus[0] : error ); }); - stream.on('end', () => { - if (errorStatus.length) { - reject(errorStatus); - } else { - resolve(); - } - }); + stream.on('end', () => + errorStatus.length ? reject(errorStatus) : resolve() + ); }); } From 79503ef9c09ffd5bb2e6e011e620c4c402059f95 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 14:49:37 +0200 Subject: [PATCH 36/45] removed debug log. Signed-off-by: Akos Kitta --- arduino-ide-extension/src/node/core-client-provider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arduino-ide-extension/src/node/core-client-provider.ts b/arduino-ide-extension/src/node/core-client-provider.ts index f64de1b5d..1d11f9720 100644 --- a/arduino-ide-extension/src/node/core-client-provider.ts +++ b/arduino-ide-extension/src/node/core-client-provider.ts @@ -86,7 +86,7 @@ export class CoreClientProvider extends GrpcClientProvider Date: Fri, 27 May 2022 15:16:37 +0200 Subject: [PATCH 37/45] run core and lib index updates parallel. Signed-off-by: Akos Kitta --- .../src/node/core-client-provider.ts | 50 ++++--------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/arduino-ide-extension/src/node/core-client-provider.ts b/arduino-ide-extension/src/node/core-client-provider.ts index 1d11f9720..c585afeda 100644 --- a/arduino-ide-extension/src/node/core-client-provider.ts +++ b/arduino-ide-extension/src/node/core-client-provider.ts @@ -20,7 +20,7 @@ import { } from './cli-protocol/cc/arduino/cli/commands/v1/commands_pb'; import * as commandsGrpcPb from './cli-protocol/cc/arduino/cli/commands/v1/commands_grpc_pb'; import { NotificationServiceServer } from '../common/protocol'; -import { Deferred } from '@theia/core/lib/common/promise-util'; +import { Deferred, retry } from '@theia/core/lib/common/promise-util'; import { Status as RpcStatus } from './cli-protocol/google/rpc/status_pb'; @injectable() @@ -232,45 +232,15 @@ export class CoreClientProvider extends GrpcClientProvider { - // in a separate promise, try and update the index - let indexUpdateSucceeded = true; - for (let i = 0; i < 10; i++) { - try { - await this.updateIndex({ client, instance }); - indexUpdateSucceeded = true; - break; - } catch (e) { - console.error(`Error while updating index in attempt ${i}.`, e); - } - } - if (!indexUpdateSucceeded) { - console.error('Could not update the index. Please restart to try again.'); - } - - let libIndexUpdateSucceeded = true; - for (let i = 0; i < 10; i++) { - try { - await this.updateLibraryIndex({ client, instance }); - libIndexUpdateSucceeded = true; - break; - } catch (e) { - console.error(`Error while updating library index in attempt ${i}.`, e); - } - } - if (!libIndexUpdateSucceeded) { - console.error( - 'Could not update the library index. Please restart to try again.' - ); - } - - if (indexUpdateSucceeded && libIndexUpdateSucceeded) { - this.notificationService.notifyIndexUpdated(); - } - return { client, instance }; + protected async updateIndexes( + client: CoreClientProvider.Client + ): Promise { + await Promise.all([ + retry(() => this.updateIndex(client), 50, 3), + retry(() => this.updateLibraryIndex(client), 50, 3), + ]); + this.notificationService.notifyIndexUpdated(); + return client; } protected async updateLibraryIndex({ From efe7399ea3e8ea6f1a2014f2be59027ea8245f3c Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 15:59:15 +0200 Subject: [PATCH 38/45] Use nightly (20220527) CLI and 2.2.0 FW uploader. Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 4 +- .../arduino/cli/commands/v1/commands_pb.d.ts | 17 ++ .../cc/arduino/cli/commands/v1/commands_pb.js | 120 +++++++++++- .../cc/arduino/cli/commands/v1/common_pb.d.ts | 25 +++ .../cc/arduino/cli/commands/v1/common_pb.js | 182 ++++++++++++++++++ .../arduino/cli/commands/v1/compile_pb.d.ts | 12 ++ .../cc/arduino/cli/commands/v1/compile_pb.js | 92 ++++++++- .../cc/arduino/cli/commands/v1/upload_pb.d.ts | 4 - .../cc/arduino/cli/commands/v1/upload_pb.js | 32 +-- 9 files changed, 446 insertions(+), 42 deletions(-) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index b9b7304a0..cd01db060 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -157,10 +157,10 @@ ], "arduino": { "cli": { - "version": "0.21.0" + "version": "20220527" }, "fwuploader": { - "version": "2.0.0" + "version": "2.2.0" }, "clangd": { "version": "13.0.0" diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.d.ts b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.d.ts index 94ceab14f..a15ce4719 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.d.ts +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.d.ts @@ -62,6 +62,12 @@ export class InitRequest extends jspb.Message { getInstance(): cc_arduino_cli_commands_v1_common_pb.Instance | undefined; setInstance(value?: cc_arduino_cli_commands_v1_common_pb.Instance): InitRequest; + getProfile(): string; + setProfile(value: string): InitRequest; + + getSketchPath(): string; + setSketchPath(value: string): InitRequest; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): InitRequest.AsObject; @@ -76,6 +82,8 @@ export class InitRequest extends jspb.Message { export namespace InitRequest { export type AsObject = { instance?: cc_arduino_cli_commands_v1_common_pb.Instance.AsObject, + profile: string, + sketchPath: string, } } @@ -93,6 +101,12 @@ export class InitResponse extends jspb.Message { setError(value?: google_rpc_status_pb.Status): InitResponse; + hasProfile(): boolean; + clearProfile(): void; + getProfile(): cc_arduino_cli_commands_v1_common_pb.Profile | undefined; + setProfile(value?: cc_arduino_cli_commands_v1_common_pb.Profile): InitResponse; + + getMessageCase(): InitResponse.MessageCase; serializeBinary(): Uint8Array; @@ -109,6 +123,7 @@ export namespace InitResponse { export type AsObject = { initProgress?: InitResponse.Progress.AsObject, error?: google_rpc_status_pb.Status.AsObject, + profile?: cc_arduino_cli_commands_v1_common_pb.Profile.AsObject, } @@ -151,6 +166,8 @@ export namespace InitResponse { ERROR = 2, + PROFILE = 3, + } } diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.js b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.js index 1937aa229..820634067 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.js +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/commands_pb.js @@ -866,7 +866,9 @@ proto.cc.arduino.cli.commands.v1.InitRequest.prototype.toObject = function(opt_i */ proto.cc.arduino.cli.commands.v1.InitRequest.toObject = function(includeInstance, msg) { var f, obj = { - instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f) + instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f), + profile: jspb.Message.getFieldWithDefault(msg, 2, ""), + sketchPath: jspb.Message.getFieldWithDefault(msg, 3, "") }; if (includeInstance) { @@ -908,6 +910,14 @@ proto.cc.arduino.cli.commands.v1.InitRequest.deserializeBinaryFromReader = funct reader.readMessage(value,cc_arduino_cli_commands_v1_common_pb.Instance.deserializeBinaryFromReader); msg.setInstance(value); break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setProfile(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setSketchPath(value); + break; default: reader.skipField(); break; @@ -945,6 +955,20 @@ proto.cc.arduino.cli.commands.v1.InitRequest.serializeBinaryToWriter = function( cc_arduino_cli_commands_v1_common_pb.Instance.serializeBinaryToWriter ); } + f = message.getProfile(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getSketchPath(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } }; @@ -985,6 +1009,42 @@ proto.cc.arduino.cli.commands.v1.InitRequest.prototype.hasInstance = function() }; +/** + * optional string profile = 2; + * @return {string} + */ +proto.cc.arduino.cli.commands.v1.InitRequest.prototype.getProfile = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.cc.arduino.cli.commands.v1.InitRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.InitRequest.prototype.setProfile = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string sketch_path = 3; + * @return {string} + */ +proto.cc.arduino.cli.commands.v1.InitRequest.prototype.getSketchPath = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.cc.arduino.cli.commands.v1.InitRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.InitRequest.prototype.setSketchPath = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + /** * Oneof group definitions for this message. Each group defines the field @@ -994,7 +1054,7 @@ proto.cc.arduino.cli.commands.v1.InitRequest.prototype.hasInstance = function() * @private {!Array>} * @const */ -proto.cc.arduino.cli.commands.v1.InitResponse.oneofGroups_ = [[1,2]]; +proto.cc.arduino.cli.commands.v1.InitResponse.oneofGroups_ = [[1,2,3]]; /** * @enum {number} @@ -1002,7 +1062,8 @@ proto.cc.arduino.cli.commands.v1.InitResponse.oneofGroups_ = [[1,2]]; proto.cc.arduino.cli.commands.v1.InitResponse.MessageCase = { MESSAGE_NOT_SET: 0, INIT_PROGRESS: 1, - ERROR: 2 + ERROR: 2, + PROFILE: 3 }; /** @@ -1044,7 +1105,8 @@ proto.cc.arduino.cli.commands.v1.InitResponse.prototype.toObject = function(opt_ proto.cc.arduino.cli.commands.v1.InitResponse.toObject = function(includeInstance, msg) { var f, obj = { initProgress: (f = msg.getInitProgress()) && proto.cc.arduino.cli.commands.v1.InitResponse.Progress.toObject(includeInstance, f), - error: (f = msg.getError()) && google_rpc_status_pb.Status.toObject(includeInstance, f) + error: (f = msg.getError()) && google_rpc_status_pb.Status.toObject(includeInstance, f), + profile: (f = msg.getProfile()) && cc_arduino_cli_commands_v1_common_pb.Profile.toObject(includeInstance, f) }; if (includeInstance) { @@ -1091,6 +1153,11 @@ proto.cc.arduino.cli.commands.v1.InitResponse.deserializeBinaryFromReader = func reader.readMessage(value,google_rpc_status_pb.Status.deserializeBinaryFromReader); msg.setError(value); break; + case 3: + var value = new cc_arduino_cli_commands_v1_common_pb.Profile; + reader.readMessage(value,cc_arduino_cli_commands_v1_common_pb.Profile.deserializeBinaryFromReader); + msg.setProfile(value); + break; default: reader.skipField(); break; @@ -1136,6 +1203,14 @@ proto.cc.arduino.cli.commands.v1.InitResponse.serializeBinaryToWriter = function google_rpc_status_pb.Status.serializeBinaryToWriter ); } + f = message.getProfile(); + if (f != null) { + writer.writeMessage( + 3, + f, + cc_arduino_cli_commands_v1_common_pb.Profile.serializeBinaryToWriter + ); + } }; @@ -1415,6 +1490,43 @@ proto.cc.arduino.cli.commands.v1.InitResponse.prototype.hasError = function() { }; +/** + * optional Profile profile = 3; + * @return {?proto.cc.arduino.cli.commands.v1.Profile} + */ +proto.cc.arduino.cli.commands.v1.InitResponse.prototype.getProfile = function() { + return /** @type{?proto.cc.arduino.cli.commands.v1.Profile} */ ( + jspb.Message.getWrapperField(this, cc_arduino_cli_commands_v1_common_pb.Profile, 3)); +}; + + +/** + * @param {?proto.cc.arduino.cli.commands.v1.Profile|undefined} value + * @return {!proto.cc.arduino.cli.commands.v1.InitResponse} returns this +*/ +proto.cc.arduino.cli.commands.v1.InitResponse.prototype.setProfile = function(value) { + return jspb.Message.setOneofWrapperField(this, 3, proto.cc.arduino.cli.commands.v1.InitResponse.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.cc.arduino.cli.commands.v1.InitResponse} returns this + */ +proto.cc.arduino.cli.commands.v1.InitResponse.prototype.clearProfile = function() { + return this.setProfile(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.cc.arduino.cli.commands.v1.InitResponse.prototype.hasProfile = function() { + return jspb.Message.getField(this, 3) != null; +}; + + diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.d.ts b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.d.ts index 571b58afe..2d273542c 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.d.ts +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.d.ts @@ -234,3 +234,28 @@ export namespace Board { fqbn: string, } } + +export class Profile extends jspb.Message { + getName(): string; + setName(value: string): Profile; + + getFqbn(): string; + setFqbn(value: string): Profile; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Profile.AsObject; + static toObject(includeInstance: boolean, msg: Profile): Profile.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: Profile, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Profile; + static deserializeBinaryFromReader(message: Profile, reader: jspb.BinaryReader): Profile; +} + +export namespace Profile { + export type AsObject = { + name: string, + fqbn: string, + } +} diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.js b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.js index efd86871e..67098a306 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.js +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/common_pb.js @@ -20,6 +20,7 @@ goog.exportSymbol('proto.cc.arduino.cli.commands.v1.DownloadProgress', null, glo goog.exportSymbol('proto.cc.arduino.cli.commands.v1.Instance', null, global); goog.exportSymbol('proto.cc.arduino.cli.commands.v1.Platform', null, global); goog.exportSymbol('proto.cc.arduino.cli.commands.v1.PlatformReference', null, global); +goog.exportSymbol('proto.cc.arduino.cli.commands.v1.Profile', null, global); goog.exportSymbol('proto.cc.arduino.cli.commands.v1.Programmer', null, global); goog.exportSymbol('proto.cc.arduino.cli.commands.v1.TaskProgress', null, global); /** @@ -169,6 +170,27 @@ if (goog.DEBUG && !COMPILED) { */ proto.cc.arduino.cli.commands.v1.Board.displayName = 'proto.cc.arduino.cli.commands.v1.Board'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.cc.arduino.cli.commands.v1.Profile = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.cc.arduino.cli.commands.v1.Profile, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.cc.arduino.cli.commands.v1.Profile.displayName = 'proto.cc.arduino.cli.commands.v1.Profile'; +} @@ -1709,4 +1731,164 @@ proto.cc.arduino.cli.commands.v1.Board.prototype.setFqbn = function(value) { }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.cc.arduino.cli.commands.v1.Profile.prototype.toObject = function(opt_includeInstance) { + return proto.cc.arduino.cli.commands.v1.Profile.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.cc.arduino.cli.commands.v1.Profile} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.cc.arduino.cli.commands.v1.Profile.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + fqbn: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.cc.arduino.cli.commands.v1.Profile} + */ +proto.cc.arduino.cli.commands.v1.Profile.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.cc.arduino.cli.commands.v1.Profile; + return proto.cc.arduino.cli.commands.v1.Profile.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.cc.arduino.cli.commands.v1.Profile} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.cc.arduino.cli.commands.v1.Profile} + */ +proto.cc.arduino.cli.commands.v1.Profile.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setFqbn(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.cc.arduino.cli.commands.v1.Profile.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.cc.arduino.cli.commands.v1.Profile.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.cc.arduino.cli.commands.v1.Profile} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.cc.arduino.cli.commands.v1.Profile.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getFqbn(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.cc.arduino.cli.commands.v1.Profile.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.cc.arduino.cli.commands.v1.Profile} returns this + */ +proto.cc.arduino.cli.commands.v1.Profile.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string fqbn = 2; + * @return {string} + */ +proto.cc.arduino.cli.commands.v1.Profile.prototype.getFqbn = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.cc.arduino.cli.commands.v1.Profile} returns this + */ +proto.cc.arduino.cli.commands.v1.Profile.prototype.setFqbn = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + goog.object.extend(exports, proto.cc.arduino.cli.commands.v1); diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts index 7613a69fd..c0ba371ca 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.d.ts @@ -86,6 +86,15 @@ export class CompileRequest extends jspb.Message { setLibraryList(value: Array): CompileRequest; addLibrary(value: string, index?: number): string; + getKeysKeychain(): string; + setKeysKeychain(value: string): CompileRequest; + + getSignKey(): string; + setSignKey(value: string): CompileRequest; + + getEncryptKey(): string; + setEncryptKey(value: string): CompileRequest; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): CompileRequest.AsObject; @@ -121,6 +130,9 @@ export namespace CompileRequest { sourceOverrideMap: Array<[string, string]>, exportBinaries?: google_protobuf_wrappers_pb.BoolValue.AsObject, libraryList: Array, + keysKeychain: string, + signKey: string, + encryptKey: string, } } diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js index 1d2bd8977..168deb3c6 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/compile_pb.js @@ -146,7 +146,10 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.toObject = function(includeInsta createCompilationDatabaseOnly: jspb.Message.getBooleanFieldWithDefault(msg, 21, false), sourceOverrideMap: (f = msg.getSourceOverrideMap()) ? f.toObject(includeInstance, undefined) : [], exportBinaries: (f = msg.getExportBinaries()) && google_protobuf_wrappers_pb.BoolValue.toObject(includeInstance, f), - libraryList: (f = jspb.Message.getRepeatedField(msg, 24)) == null ? undefined : f + libraryList: (f = jspb.Message.getRepeatedField(msg, 24)) == null ? undefined : f, + keysKeychain: jspb.Message.getFieldWithDefault(msg, 25, ""), + signKey: jspb.Message.getFieldWithDefault(msg, 26, ""), + encryptKey: jspb.Message.getFieldWithDefault(msg, 27, "") }; if (includeInstance) { @@ -271,6 +274,18 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.deserializeBinaryFromReader = fu var value = /** @type {string} */ (reader.readString()); msg.addLibrary(value); break; + case 25: + var value = /** @type {string} */ (reader.readString()); + msg.setKeysKeychain(value); + break; + case 26: + var value = /** @type {string} */ (reader.readString()); + msg.setSignKey(value); + break; + case 27: + var value = /** @type {string} */ (reader.readString()); + msg.setEncryptKey(value); + break; default: reader.skipField(); break; @@ -446,6 +461,27 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.serializeBinaryToWriter = functi f ); } + f = message.getKeysKeychain(); + if (f.length > 0) { + writer.writeString( + 25, + f + ); + } + f = message.getSignKey(); + if (f.length > 0) { + writer.writeString( + 26, + f + ); + } + f = message.getEncryptKey(); + if (f.length > 0) { + writer.writeString( + 27, + f + ); + } }; @@ -926,6 +962,60 @@ proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.clearLibraryList = fun }; +/** + * optional string keys_keychain = 25; + * @return {string} + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.getKeysKeychain = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 25, "")); +}; + + +/** + * @param {string} value + * @return {!proto.cc.arduino.cli.commands.v1.CompileRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.setKeysKeychain = function(value) { + return jspb.Message.setProto3StringField(this, 25, value); +}; + + +/** + * optional string sign_key = 26; + * @return {string} + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.getSignKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 26, "")); +}; + + +/** + * @param {string} value + * @return {!proto.cc.arduino.cli.commands.v1.CompileRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.setSignKey = function(value) { + return jspb.Message.setProto3StringField(this, 26, value); +}; + + +/** + * optional string encrypt_key = 27; + * @return {string} + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.getEncryptKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 27, "")); +}; + + +/** + * @param {string} value + * @return {!proto.cc.arduino.cli.commands.v1.CompileRequest} returns this + */ +proto.cc.arduino.cli.commands.v1.CompileRequest.prototype.setEncryptKey = function(value) { + return jspb.Message.setProto3StringField(this, 27, value); +}; + + /** * List of repeated fields within this message type. diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.d.ts b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.d.ts index 1c1ca38ca..4427473a6 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.d.ts +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.d.ts @@ -371,9 +371,6 @@ export class SupportedUserFieldsRequest extends jspb.Message { getProtocol(): string; setProtocol(value: string): SupportedUserFieldsRequest; - getAddress(): string; - setAddress(value: string): SupportedUserFieldsRequest; - serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): SupportedUserFieldsRequest.AsObject; @@ -390,7 +387,6 @@ export namespace SupportedUserFieldsRequest { instance?: cc_arduino_cli_commands_v1_common_pb.Instance.AsObject, fqbn: string, protocol: string, - address: string, } } diff --git a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.js b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.js index 87914c167..8841575ad 100644 --- a/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.js +++ b/arduino-ide-extension/src/node/cli-protocol/cc/arduino/cli/commands/v1/upload_pb.js @@ -2718,8 +2718,7 @@ proto.cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.toObject = function( var f, obj = { instance: (f = msg.getInstance()) && cc_arduino_cli_commands_v1_common_pb.Instance.toObject(includeInstance, f), fqbn: jspb.Message.getFieldWithDefault(msg, 2, ""), - protocol: jspb.Message.getFieldWithDefault(msg, 3, ""), - address: jspb.Message.getFieldWithDefault(msg, 4, "") + protocol: jspb.Message.getFieldWithDefault(msg, 3, "") }; if (includeInstance) { @@ -2769,10 +2768,6 @@ proto.cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.deserializeBinaryFro var value = /** @type {string} */ (reader.readString()); msg.setProtocol(value); break; - case 4: - var value = /** @type {string} */ (reader.readString()); - msg.setAddress(value); - break; default: reader.skipField(); break; @@ -2824,13 +2819,6 @@ proto.cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.serializeBinaryToWri f ); } - f = message.getAddress(); - if (f.length > 0) { - writer.writeString( - 4, - f - ); - } }; @@ -2907,24 +2895,6 @@ proto.cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.prototype.setProtoco }; -/** - * optional string address = 4; - * @return {string} - */ -proto.cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.prototype.getAddress = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); -}; - - -/** - * @param {string} value - * @return {!proto.cc.arduino.cli.commands.v1.SupportedUserFieldsRequest} returns this - */ -proto.cc.arduino.cli.commands.v1.SupportedUserFieldsRequest.prototype.setAddress = function(value) { - return jspb.Message.setProto3StringField(this, 4, value); -}; - - From 05af64153b943779a19f7083661d5bcd54f1fde1 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 16:56:15 +0200 Subject: [PATCH 39/45] Defer loading boards until the app is ready. Signed-off-by: Akos Kitta --- .../boards/boards-config-dialog-widget.tsx | 1 + .../src/browser/boards/boards-config.tsx | 20 ++++++++++++------- .../src/browser/notification-center.ts | 15 ++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx b/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx index a21066bd1..7ad65697a 100644 --- a/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx +++ b/arduino-ide-extension/src/browser/boards/boards-config-dialog-widget.tsx @@ -55,6 +55,7 @@ export class BoardsConfigDialogWidget extends ReactWidget { onConfigChange={this.fireConfigChanged} onFocusNodeSet={this.setFocusNode} onFilteredTextDidChangeEvent={this.onFilterTextDidChangeEmitter.event} + onAppStateDidChange={this.notificationCenter.onAppStateDidChange} />
); diff --git a/arduino-ide-extension/src/browser/boards/boards-config.tsx b/arduino-ide-extension/src/browser/boards/boards-config.tsx index c0a552221..1a80ced5d 100644 --- a/arduino-ide-extension/src/browser/boards/boards-config.tsx +++ b/arduino-ide-extension/src/browser/boards/boards-config.tsx @@ -16,6 +16,7 @@ import { } from './boards-service-provider'; import { naturalCompare } from '../../common/utils'; import { nls } from '@theia/core/lib/common'; +import { FrontendApplicationState } from '@theia/core/lib/common/frontend-application-state'; export namespace BoardsConfig { export interface Config { @@ -29,6 +30,7 @@ export namespace BoardsConfig { readonly onConfigChange: (config: Config) => void; readonly onFocusNodeSet: (element: HTMLElement | undefined) => void; readonly onFilteredTextDidChangeEvent: Event; + readonly onAppStateDidChange: Event; } export interface State extends Config { @@ -99,14 +101,18 @@ export class BoardsConfig extends React.Component< }; } - override componentDidMount() { - this.updateBoards(); - this.updatePorts( - this.props.boardsServiceProvider.availableBoards - .map(({ port }) => port) - .filter(notEmpty) - ); + override componentDidMount(): void { this.toDispose.pushAll([ + this.props.onAppStateDidChange((state) => { + if (state === 'ready') { + this.updateBoards(); + this.updatePorts( + this.props.boardsServiceProvider.availableBoards + .map(({ port }) => port) + .filter(notEmpty) + ); + } + }), this.props.notificationCenter.onAttachedBoardsChanged((event) => this.updatePorts( event.newState.ports, diff --git a/arduino-ide-extension/src/browser/notification-center.ts b/arduino-ide-extension/src/browser/notification-center.ts index 13ecd6041..b6ad3b4b6 100644 --- a/arduino-ide-extension/src/browser/notification-center.ts +++ b/arduino-ide-extension/src/browser/notification-center.ts @@ -18,6 +18,10 @@ import { Config, Sketch, } from '../common/protocol'; +import { + FrontendApplicationStateService, + FrontendApplicationState, +} from '@theia/core/lib/browser/frontend-application-state'; @injectable() export class NotificationCenter @@ -26,6 +30,9 @@ export class NotificationCenter @inject(NotificationServiceServer) protected readonly server: JsonRpcProxy; + @inject(FrontendApplicationStateService) + private readonly appStateService: FrontendApplicationStateService; + protected readonly indexUpdatedEmitter = new Emitter(); protected readonly daemonStartedEmitter = new Emitter(); protected readonly daemonStoppedEmitter = new Emitter(); @@ -49,6 +56,8 @@ export class NotificationCenter protected readonly recentSketchesChangedEmitter = new Emitter<{ sketches: Sketch[]; }>(); + private readonly onAppStateDidChangeEmitter = + new Emitter(); protected readonly toDispose = new DisposableCollection( this.indexUpdatedEmitter, @@ -72,10 +81,16 @@ export class NotificationCenter readonly onLibraryUninstalled = this.libraryUninstalledEmitter.event; readonly onAttachedBoardsChanged = this.attachedBoardsChangedEmitter.event; readonly onRecentSketchesChanged = this.recentSketchesChangedEmitter.event; + readonly onAppStateDidChange = this.onAppStateDidChangeEmitter.event; @postConstruct() protected init(): void { this.server.setClient(this); + this.toDispose.push( + this.appStateService.onStateChanged((state) => + this.onAppStateDidChangeEmitter.fire(state) + ) + ); } onStop(): void { From b947be027dc01a075743affb15b86bb617526efa Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 16:59:27 +0200 Subject: [PATCH 40/45] Open devtools when tracing. Signed-off-by: Akos Kitta --- .vscode/launch.json | 3 ++- .../src/electron-main/theia/electron-main-application.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c50d311c7..802b130d6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,7 +21,8 @@ "--plugins=local-dir:../plugins", "--hosted-plugin-inspect=9339", "--nosplash", - "--content-trace" + "--content-trace", + "--open-devtools" ], "env": { "NODE_ENV": "development" diff --git a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts index 1aa11ea31..e91453312 100644 --- a/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts +++ b/arduino-ide-extension/src/electron-main/theia/electron-main-application.ts @@ -327,7 +327,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication { ): Promise { const electronWindow = await super.createWindow(options); if (APP_STARTED_WITH_DEV_TOOLS) { - electronWindow.webContents.openDevTools({ mode: 'undocked' }); + electronWindow.webContents.openDevTools(); } this.attachListenersToWindow(electronWindow); return electronWindow; From 2fbf3cbb1ef30aa92ad2660ef135e86130e9aed2 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 27 May 2022 18:43:42 +0200 Subject: [PATCH 41/45] Resolve and cache current sketch. Signed-off-by: Akos Kitta --- .../browser/arduino-frontend-contribution.tsx | 12 +++++-- .../src/browser/contributions/add-file.ts | 3 +- .../browser/contributions/archive-sketch.ts | 3 +- .../src/browser/contributions/close.ts | 3 +- .../src/browser/contributions/contribution.ts | 7 ++-- .../src/browser/contributions/debug.ts | 3 +- .../browser/contributions/include-library.ts | 3 +- .../browser/contributions/save-as-sketch.ts | 3 +- .../src/browser/contributions/save-sketch.ts | 3 +- .../browser/contributions/sketch-control.ts | 34 +++++++++---------- .../browser/contributions/upload-sketch.ts | 3 +- .../browser/contributions/verify-sketch.ts | 3 +- .../browser/theia/core/application-shell.ts | 4 +-- .../debug/debug-configuration-manager.ts | 7 ++-- .../theia/editor/editor-widget-factory.ts | 7 ++-- .../theia/workspace/workspace-commands.ts | 11 +++--- .../workspace/workspace-delete-handler.ts | 7 ++-- .../workspace-variable-contribution.ts | 20 +++++++---- .../cloud-sketchbook-contributions.ts | 5 +-- .../sketchbook/sketchbook-tree-model.ts | 7 ++-- .../sketchbook/sketchbook-tree-widget.tsx | 7 ++-- .../sketchbook-widget-contribution.ts | 10 ++++-- .../protocol/sketches-service-client-impl.ts | 34 +++++++++++++------ .../src/node/board-discovery.ts | 4 +-- 24 files changed, 132 insertions(+), 71 deletions(-) diff --git a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx index 313eaf414..24e712671 100644 --- a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx +++ b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx @@ -66,7 +66,10 @@ import { ArduinoMenus } from './menu/arduino-menus'; import { MonitorViewContribution } from './serial/monitor/monitor-view-contribution'; import { ArduinoToolbar } from './toolbar/arduino-toolbar'; import { ArduinoPreferences } from './arduino-preferences'; -import { SketchesServiceClientImpl } from '../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../common/protocol/sketches-service-client-impl'; import { SaveAsSketch } from './contributions/save-as-sketch'; import { IDEUpdaterDialog } from './dialogs/ide-updater/ide-updater-dialog'; import { IDEUpdater } from '../common/protocol/ide-updater'; @@ -219,7 +222,10 @@ export class ArduinoFrontendContribution updateStatusBar(this.boardsServiceClientImpl.boardsConfig); this.appStateService.reachedState('ready').then(async () => { const sketch = await this.sketchServiceClient.currentSketch(); - if (sketch && !(await this.sketchService.isTemp(sketch))) { + if ( + CurrentSketch.isValid(sketch) && + !(await this.sketchService.isTemp(sketch)) + ) { this.toDisposeOnStop.push(this.fileService.watch(new URI(sketch.uri))); this.toDisposeOnStop.push( this.fileService.onDidFilesChange(async (event) => { @@ -373,7 +379,7 @@ export class ArduinoFrontendContribution let currentSketchPath: string | undefined = undefined; if (log) { const currentSketch = await this.sketchServiceClient.currentSketch(); - if (currentSketch) { + if (CurrentSketch.isValid(currentSketch)) { currentSketchPath = await this.fileService.fsPath( new URI(currentSketch.uri) ); diff --git a/arduino-ide-extension/src/browser/contributions/add-file.ts b/arduino-ide-extension/src/browser/contributions/add-file.ts index 4285ec08a..b7cb48f73 100644 --- a/arduino-ide-extension/src/browser/contributions/add-file.ts +++ b/arduino-ide-extension/src/browser/contributions/add-file.ts @@ -10,6 +10,7 @@ import { } from './contribution'; import { FileDialogService } from '@theia/filesystem/lib/browser'; import { nls } from '@theia/core/lib/common'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; @injectable() export class AddFile extends SketchContribution { @@ -32,7 +33,7 @@ export class AddFile extends SketchContribution { protected async addFile(): Promise { const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } const toAddUri = await this.fileDialogService.showOpenDialog({ diff --git a/arduino-ide-extension/src/browser/contributions/archive-sketch.ts b/arduino-ide-extension/src/browser/contributions/archive-sketch.ts index bf7e09e7e..abe22d77f 100644 --- a/arduino-ide-extension/src/browser/contributions/archive-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/archive-sketch.ts @@ -10,6 +10,7 @@ import { MenuModelRegistry, } from './contribution'; import { nls } from '@theia/core/lib/common'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; @injectable() export class ArchiveSketch extends SketchContribution { @@ -32,7 +33,7 @@ export class ArchiveSketch extends SketchContribution { this.sketchServiceClient.currentSketch(), this.configService.getConfiguration(), ]); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } const archiveBasename = `${sketch.name}-${dateFormat( diff --git a/arduino-ide-extension/src/browser/contributions/close.ts b/arduino-ide-extension/src/browser/contributions/close.ts index 3658be152..ffae12539 100644 --- a/arduino-ide-extension/src/browser/contributions/close.ts +++ b/arduino-ide-extension/src/browser/contributions/close.ts @@ -16,6 +16,7 @@ import { URI, } from './contribution'; import { nls } from '@theia/core/lib/common'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; /** * Closes the `current` closeable editor, or any closeable current widget from the main area, or the current sketch window. @@ -54,7 +55,7 @@ export class Close extends SketchContribution { // Close the sketch (window). const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } const isTemp = await this.sketchService.isTemp(sketch); diff --git a/arduino-ide-extension/src/browser/contributions/contribution.ts b/arduino-ide-extension/src/browser/contributions/contribution.ts index cea483311..1597cac28 100644 --- a/arduino-ide-extension/src/browser/contributions/contribution.ts +++ b/arduino-ide-extension/src/browser/contributions/contribution.ts @@ -39,7 +39,10 @@ import { } from '@theia/core/lib/common/command'; import { EditorMode } from '../editor-mode'; import { SettingsService } from '../dialogs/settings/settings'; -import { SketchesServiceClientImpl } from '../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../common/protocol/sketches-service-client-impl'; import { SketchesService, ConfigService, @@ -149,7 +152,7 @@ export abstract class SketchContribution extends Contribution { protected async sourceOverride(): Promise> { const override: Record = {}; const sketch = await this.sketchServiceClient.currentSketch(); - if (sketch) { + if (CurrentSketch.isValid(sketch)) { for (const editor of this.editorManager.all) { const uri = editor.editor.uri; if (Saveable.isDirty(editor) && Sketch.isInSketch(uri, sketch)) { diff --git a/arduino-ide-extension/src/browser/contributions/debug.ts b/arduino-ide-extension/src/browser/contributions/debug.ts index 692901cf5..b1550ce32 100644 --- a/arduino-ide-extension/src/browser/contributions/debug.ts +++ b/arduino-ide-extension/src/browser/contributions/debug.ts @@ -13,6 +13,7 @@ import { TabBarToolbarRegistry, } from './contribution'; import { MaybePromise, nls } from '@theia/core/lib/common'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; @injectable() export class Debug extends SketchContribution { @@ -160,7 +161,7 @@ export class Debug extends SketchContribution { this.sketchServiceClient.currentSketch(), this.executableService.list(), ]); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } const ideTempFolderUri = await this.sketchService.getIdeTempFolderUri( diff --git a/arduino-ide-extension/src/browser/contributions/include-library.ts b/arduino-ide-extension/src/browser/contributions/include-library.ts index 4b31965ae..7347c3fa9 100644 --- a/arduino-ide-extension/src/browser/contributions/include-library.ts +++ b/arduino-ide-extension/src/browser/contributions/include-library.ts @@ -17,6 +17,7 @@ import { SketchContribution, Command, CommandRegistry } from './contribution'; import { NotificationCenter } from '../notification-center'; import { nls } from '@theia/core/lib/common'; import * as monaco from '@theia/monaco-editor-core'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; @injectable() export class IncludeLibrary extends SketchContribution { @@ -172,7 +173,7 @@ export class IncludeLibrary extends SketchContribution { protected async includeLibrary(library: LibraryPackage): Promise { const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } // If the current editor is one of the additional files from the sketch, we use that. diff --git a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts index 2cd709a42..6aa63f30e 100644 --- a/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/save-as-sketch.ts @@ -14,6 +14,7 @@ import { nls } from '@theia/core/lib/common'; import { ApplicationShell, NavigatableWidget, Saveable } from '@theia/core/lib/browser'; import { EditorManager } from '@theia/editor/lib/browser'; import { WindowService } from '@theia/core/lib/browser/window/window-service'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; @injectable() export class SaveAsSketch extends SketchContribution { @@ -59,7 +60,7 @@ export class SaveAsSketch extends SketchContribution { }: SaveAsSketch.Options = SaveAsSketch.Options.DEFAULT ): Promise { const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return false; } diff --git a/arduino-ide-extension/src/browser/contributions/save-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-sketch.ts index 0df21d32c..2c1ab550e 100644 --- a/arduino-ide-extension/src/browser/contributions/save-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/save-sketch.ts @@ -12,6 +12,7 @@ import { TabBarToolbarRegistry, } from './contribution'; import { nls } from '@theia/core/lib/common'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; @injectable() export class SaveSketch extends SketchContribution { @@ -53,7 +54,7 @@ export class SaveSketch extends SketchContribution { async saveSketch(): Promise { const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } const isTemp = await this.sketchService.isTemp(sketch); diff --git a/arduino-ide-extension/src/browser/contributions/sketch-control.ts b/arduino-ide-extension/src/browser/contributions/sketch-control.ts index d8a967847..ea376fea1 100644 --- a/arduino-ide-extension/src/browser/contributions/sketch-control.ts +++ b/arduino-ide-extension/src/browser/contributions/sketch-control.ts @@ -19,7 +19,10 @@ import { } from './contribution'; import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus'; import { EditorManager } from '@theia/editor/lib/browser/editor-manager'; -import { SketchesServiceClientImpl } from '../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../common/protocol/sketches-service-client-impl'; import { LocalCacheFsProvider } from '../local-cache/local-cache-fs-provider'; import { nls } from '@theia/core/lib/common'; @@ -55,7 +58,7 @@ export class SketchControl extends SketchContribution { execute: async () => { this.toDisposeBeforeCreateNewContextMenu.dispose(); const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } @@ -70,25 +73,22 @@ export class SketchControl extends SketchContribution { return; } - const { mainFileUri, rootFolderFileUris } = - await this.sketchService.loadSketch(sketch.uri); + const { mainFileUri, rootFolderFileUris } = sketch; const uris = [mainFileUri, ...rootFolderFileUris]; - const currentSketch = - await this.sketchesServiceClient.currentSketch(); - const parentsketchUri = this.editorManager.currentEditor + const parentSketchUri = this.editorManager.currentEditor ?.getResourceUri() ?.toString(); - const parentsketch = await this.sketchService.getSketchFolder( - parentsketchUri || '' + const parentSketch = await this.sketchService.getSketchFolder( + parentSketchUri || '' ); // if the current file is in the current opened sketch, show extra menus if ( - currentSketch && - parentsketch && - parentsketch.uri === currentSketch.uri && - this.allowRename(parentsketch.uri) + sketch && + parentSketch && + parentSketch.uri === sketch.uri && + this.allowRename(parentSketch.uri) ) { this.menuRegistry.registerMenuAction( ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, @@ -122,10 +122,10 @@ export class SketchControl extends SketchContribution { } if ( - currentSketch && - parentsketch && - parentsketch.uri === currentSketch.uri && - this.allowDelete(parentsketch.uri) + sketch && + parentSketch && + parentSketch.uri === sketch.uri && + this.allowDelete(parentSketch.uri) ) { this.menuRegistry.registerMenuAction( ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts index 7c8cae2b4..f3478b1ea 100644 --- a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -16,6 +16,7 @@ import { } 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'; @injectable() export class UploadSketch extends SketchContribution { @@ -209,7 +210,7 @@ export class UploadSketch extends SketchContribution { this.uploadInProgress = true; this.onDidChangeEmitter.fire(); const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } diff --git a/arduino-ide-extension/src/browser/contributions/verify-sketch.ts b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts index e6946cba4..b22f5998a 100644 --- a/arduino-ide-extension/src/browser/contributions/verify-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts @@ -14,6 +14,7 @@ import { TabBarToolbarRegistry, } from './contribution'; import { nls } from '@theia/core/lib/common'; +import { CurrentSketch } from '../../common/protocol/sketches-service-client-impl'; @injectable() export class VerifySketch extends SketchContribution { @@ -99,7 +100,7 @@ export class VerifySketch extends SketchContribution { this.onDidChangeEmitter.fire(); const sketch = await this.sketchServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } try { diff --git a/arduino-ide-extension/src/browser/theia/core/application-shell.ts b/arduino-ide-extension/src/browser/theia/core/application-shell.ts index b7423c577..eff6a3a04 100644 --- a/arduino-ide-extension/src/browser/theia/core/application-shell.ts +++ b/arduino-ide-extension/src/browser/theia/core/application-shell.ts @@ -15,7 +15,7 @@ import { } from '@theia/core/lib/browser'; import { Sketch } from '../../../common/protocol'; import { SaveAsSketch } from '../../contributions/save-as-sketch'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { CurrentSketch, SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; import { nls } from '@theia/core/lib/common'; import URI from '@theia/core/lib/common/uri'; @@ -41,7 +41,7 @@ export class ApplicationShell extends TheiaApplicationShell { if (widget instanceof EditorWidget) { // Make the editor un-closeable asynchronously. this.sketchesServiceClient.currentSketch().then((sketch) => { - if (sketch) { + if (CurrentSketch.isValid(sketch)) { if (!this.isSketchFile(widget.editor.uri, sketch.uri)) { return; } diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts b/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts index ebe4c5c3e..0059f433c 100644 --- a/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts +++ b/arduino-ide-extension/src/browser/theia/debug/debug-configuration-manager.ts @@ -7,7 +7,10 @@ import { DebugConfiguration } from '@theia/debug/lib/common/debug-common'; import { DebugConfigurationModel as TheiaDebugConfigurationModel } from '@theia/debug/lib/browser/debug-configuration-model'; import { DebugConfigurationManager as TheiaDebugConfigurationManager } from '@theia/debug/lib/browser/debug-configuration-manager'; import { SketchesService } from '../../../common/protocol'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; import { DebugConfigurationModel } from './debug-configuration-model'; import { FileOperationError, @@ -113,7 +116,7 @@ export class DebugConfigurationManager extends TheiaDebugConfigurationManager { (TheiaDebugConfigurationModel.JsonContent & { uri: URI }) | URI | undefined > { const sketch = await this.sketchesServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return undefined; } const uri = await this.sketchesService.getIdeTempFolderUri(sketch); diff --git a/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts b/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts index 25a790b4c..dd00e1879 100644 --- a/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts +++ b/arduino-ide-extension/src/browser/theia/editor/editor-widget-factory.ts @@ -3,7 +3,10 @@ import URI from '@theia/core/lib/common/uri'; import { EditorWidget } from '@theia/editor/lib/browser'; import { LabelProvider } from '@theia/core/lib/browser'; import { EditorWidgetFactory as TheiaEditorWidgetFactory } from '@theia/editor/lib/browser/editor-widget-factory'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; import { SketchesService, Sketch } from '../../../common/protocol'; import { nls } from '@theia/core/lib/common'; @@ -28,7 +31,7 @@ export class EditorWidgetFactory extends TheiaEditorWidgetFactory { ): Promise { const sketch = await this.sketchesServiceClient.currentSketch(); const { uri } = widget.editor; - if (sketch && Sketch.isInSketch(uri, sketch)) { + if (CurrentSketch.isValid(sketch) && Sketch.isInSketch(uri, sketch)) { const isTemp = await this.sketchesService.isTemp(sketch); if (isTemp) { widget.title.caption = nls.localize( diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts index ba6ebdd09..5b864732b 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-commands.ts @@ -12,7 +12,10 @@ import { } from '@theia/workspace/lib/browser/workspace-commands'; import { Sketch, SketchesService } from '../../../common/protocol'; import { WorkspaceInputDialog } from './workspace-input-dialog'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; import { SaveAsSketch } from '../../contributions/save-as-sketch'; import { SingleTextInputDialog } from '@theia/core/lib/browser'; import { nls } from '@theia/core/lib/common'; @@ -129,15 +132,15 @@ export class WorkspaceCommandContribution extends TheiaWorkspaceCommandContribut return; } const sketch = await this.sketchesServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } // file belongs to another sketch, do not allow rename - const parentsketch = await this.sketchService.getSketchFolder( + const parentSketch = await this.sketchService.getSketchFolder( uri.toString() ); - if (parentsketch && parentsketch.uri !== sketch.uri) { + if (parentSketch && parentSketch.uri !== sketch.uri) { return; } diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts index 2ad5ab669..e3461c379 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-delete-handler.ts @@ -2,7 +2,10 @@ import { inject, injectable } from '@theia/core/shared/inversify'; import * as remote from '@theia/core/electron-shared/@electron/remote'; import URI from '@theia/core/lib/common/uri'; import { WorkspaceDeleteHandler as TheiaWorkspaceDeleteHandler } from '@theia/workspace/lib/browser/workspace-delete-handler'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; import { nls } from '@theia/core/lib/common'; @injectable() @@ -12,7 +15,7 @@ export class WorkspaceDeleteHandler extends TheiaWorkspaceDeleteHandler { override async execute(uris: URI[]): Promise { const sketch = await this.sketchesServiceClient.currentSketch(); - if (!sketch) { + if (!CurrentSketch.isValid(sketch)) { return; } // Deleting the main sketch file. diff --git a/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts b/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts index bb8f89050..1ca0b7b85 100644 --- a/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/workspace/workspace-variable-contribution.ts @@ -1,8 +1,15 @@ -import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; +import { + inject, + injectable, + postConstruct, +} from '@theia/core/shared/inversify'; import URI from '@theia/core/lib/common/uri'; import { WorkspaceVariableContribution as TheiaWorkspaceVariableContribution } from '@theia/workspace/lib/browser/workspace-variable-contribution'; import { Sketch } from '../../../common/protocol'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; @injectable() export class WorkspaceVariableContribution extends TheiaWorkspaceVariableContribution { @@ -13,10 +20,11 @@ export class WorkspaceVariableContribution extends TheiaWorkspaceVariableContrib @postConstruct() protected override init(): void { - this.sketchesServiceClient - .currentSketch() - .then() - .then((sketch) => (this.currentSketch = sketch)); + this.sketchesServiceClient.currentSketch().then((sketch) => { + if (CurrentSketch.isValid(sketch)) { + this.currentSketch = sketch; + } + }); } override getResourceUri(): URI | undefined { diff --git a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts index 322cfb08b..85e703554 100644 --- a/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts +++ b/arduino-ide-extension/src/browser/widgets/cloud-sketchbook/cloud-sketchbook-contributions.ts @@ -23,7 +23,7 @@ import { } from '@theia/core/lib/browser/preferences/preference-service'; import { ArduinoMenus, PlaceholderMenuNode } from '../../menu/arduino-menus'; import { SketchbookCommands } from '../sketchbook/sketchbook-commands'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { CurrentSketch, SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; import { Contribution } from '../../contributions/contribution'; import { ArduinoPreferences } from '../../arduino-preferences'; import { MainMenuManager } from '../../../common/main-menu-manager'; @@ -279,7 +279,8 @@ export class CloudSketchbookContribution extends Contribution { // disable the "open sketch" command for the current sketch and for those not in sync if ( !CloudSketchbookTree.CloudSketchTreeNode.isSynced(arg.node) || - (currentSketch && currentSketch.uri === arg.node.uri.toString()) + (CurrentSketch.isValid(currentSketch) && + currentSketch.uri === arg.node.uri.toString()) ) { const placeholder = new PlaceholderMenuNode( SKETCHBOOKSYNC__CONTEXT__MAIN_GROUP, diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-model.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-model.ts index 763500f10..5b567d0be 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-model.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-model.ts @@ -13,7 +13,7 @@ import { } from '@theia/core/lib/browser/tree'; import { SketchbookCommands } from './sketchbook-commands'; import { OpenerService, open } from '@theia/core/lib/browser'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { CurrentSketch, SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; import { CommandRegistry } from '@theia/core/lib/common/command'; import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state'; @@ -294,7 +294,10 @@ export class SketchbookTreeModel extends FileTreeModel { // check if the node is a file that belongs to another sketch const sketch = await this.sketchServiceClient.currentSketch(); - if (sketch && node.uri.toString().indexOf(sketch.uri) !== 0) { + if ( + CurrentSketch.isValid(sketch) && + node.uri.toString().indexOf(sketch.uri) !== 0 + ) { return false; } return true; diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx index 0d7494545..240156472 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-tree-widget.tsx @@ -14,7 +14,10 @@ import { ContextMenuRenderer } from '@theia/core/lib/browser/context-menu-render import { SketchbookTree } from './sketchbook-tree'; import { SketchbookTreeModel } from './sketchbook-tree-model'; import { ArduinoPreferences } from '../../arduino-preferences'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; import { SelectableTreeNode } from '@theia/core/lib/browser/tree/tree-selection'; import { Sketch } from '../../contributions/contribution'; import { nls } from '@theia/core/lib/common'; @@ -54,7 +57,7 @@ export class SketchbookTreeWidget extends FileTreeWidget { super.init(); // cache the current open sketch uri const currentSketch = await this.sketchServiceClient.currentSketch(); - this.currentSketchUri = (currentSketch && currentSketch.uri) || ''; + this.currentSketchUri = (CurrentSketch.isValid(currentSketch) && currentSketch.uri) || ''; } protected override createNodeClassNames(node: TreeNode, props: NodeProps): string[] { diff --git a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts index 23a0a961e..16b66a26a 100644 --- a/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts +++ b/arduino-ide-extension/src/browser/widgets/sketchbook/sketchbook-widget-contribution.ts @@ -23,7 +23,10 @@ import { Disposable, DisposableCollection, } from '@theia/core/lib/common/disposable'; -import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl'; +import { + CurrentSketch, + SketchesServiceClientImpl, +} from '../../../common/protocol/sketches-service-client-impl'; import { FileService } from '@theia/filesystem/lib/browser/file-service'; import { URI } from '../../contributions/contribution'; @@ -142,7 +145,10 @@ export class SketchbookWidgetContribution // disable the "open sketch" command for the current sketch. // otherwise make the command clickable const currentSketch = await this.sketchServiceClient.currentSketch(); - if (currentSketch && currentSketch.uri === arg.node.uri.toString()) { + if ( + CurrentSketch.isValid(currentSketch) && + currentSketch.uri === arg.node.uri.toString() + ) { const placeholder = new PlaceholderMenuNode( SKETCHBOOK__CONTEXT__MAIN_GROUP, SketchbookCommands.OPEN_NEW_WINDOW.label! diff --git a/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts b/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts index 72d543de3..1e50729d6 100644 --- a/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts +++ b/arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts @@ -16,10 +16,18 @@ import { REMOTE_SKETCHBOOK_FOLDER, } from '../../browser/utils/constants'; import * as monaco from '@theia/monaco-editor-core'; +import { Deferred } from '@theia/core/lib/common/promise-util'; const READ_ONLY_FILES = ['sketch.json']; const READ_ONLY_FILES_REMOTE = ['thingProperties.h', 'thingsProperties.h']; +export type CurrentSketch = Sketch | 'invalid'; +export namespace CurrentSketch { + export function isValid(arg: CurrentSketch | undefined): arg is Sketch { + return !!arg && arg !== 'invalid'; + } +} + @injectable() export class SketchesServiceClientImpl implements FrontendApplicationContribution @@ -41,12 +49,15 @@ export class SketchesServiceClientImpl protected toDispose = new DisposableCollection(); protected sketches = new Map(); + // TODO: rename this + event to the `onBlabla` pattern protected sketchbookDidChangeEmitter = new Emitter<{ created: SketchRef[]; removed: SketchRef[]; }>(); readonly onSketchbookDidChange = this.sketchbookDidChangeEmitter.event; + private _currentSketch = new Deferred(); + onStart(): void { this.configService.getConfiguration().then(({ sketchDirUri }) => { this.sketchService @@ -99,13 +110,16 @@ export class SketchesServiceClientImpl ); }); }); + this.loadCurrentSketch().then((currentSketch) => + this._currentSketch.resolve(currentSketch) + ); } onStop(): void { this.toDispose.dispose(); } - async currentSketch(): Promise { + private async loadCurrentSketch(): Promise { const sketches = ( await Promise.all( this.workspaceService @@ -116,7 +130,7 @@ export class SketchesServiceClientImpl ) ).filter(notEmpty); if (!sketches.length) { - return undefined; + return 'invalid'; } if (sketches.length > 1) { console.log( @@ -128,16 +142,14 @@ export class SketchesServiceClientImpl return sketches[0]; } + async currentSketch(): Promise { + return this._currentSketch.promise; + } + async currentSketchFile(): Promise { - const sketch = await this.currentSketch(); - if (sketch) { - const uri = sketch.mainFileUri; - const exists = await this.fileService.exists(new URI(uri)); - if (!exists) { - this.messageService.warn(`Could not find sketch file: ${uri}`); - return undefined; - } - return uri; + const currentSketch = await this.currentSketch(); + if (CurrentSketch.isValid(currentSketch)) { + return currentSketch.mainFileUri; } return undefined; } diff --git a/arduino-ide-extension/src/node/board-discovery.ts b/arduino-ide-extension/src/node/board-discovery.ts index 3354d53a4..dcaa43d92 100644 --- a/arduino-ide-extension/src/node/board-discovery.ts +++ b/arduino-ide-extension/src/node/board-discovery.ts @@ -55,9 +55,7 @@ export class BoardDiscovery extends CoreClientAware { @postConstruct() protected async init(): Promise { - await this.coreClientProvider.initialized; - const coreClient = await this.coreClient(); - this.startBoardListWatch(coreClient); + this.coreClient().then((client) => this.startBoardListWatch(client)); } stopBoardListWatch(coreClient: CoreClientProvider.Client): Promise { From 0e4881c1f156b9fa5a061d7e9fb68479eb0d6c7b Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 31 May 2022 16:41:57 +0200 Subject: [PATCH 42/45] Reverted titleBarStyling for Windows/Linux. Otherwise the menus are not visible. Signed-off-by: Akos Kitta --- .../electron-browser/theia/core/electron-menu-contribution.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts index 934f286fe..9327637d7 100644 --- a/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts +++ b/arduino-ide-extension/src/electron-browser/theia/core/electron-menu-contribution.ts @@ -50,10 +50,6 @@ export class ElectronMenuContribution // } } - override handleTitleBarStyling(): void { - // NOOP - } - override registerCommands(registry: CommandRegistry): void { this.theiaRegisterCommands(registry); registry.unregisterCommand(ElectronCommands.CLOSE_WINDOW); From 644bf144b25ece6f3f58a0a57f631bbe9fa934d9 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Tue, 31 May 2022 18:01:36 +0200 Subject: [PATCH 43/45] workaround for the non realpath. Signed-off-by: Akos Kitta --- arduino-ide-extension/package.json | 1 + .../src/node/sketches-service-impl.ts | 16 ++++++++++++++-- yarn.lock | 5 +++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/arduino-ide-extension/package.json b/arduino-ide-extension/package.json index cd01db060..789fd1007 100644 --- a/arduino-ide-extension/package.json +++ b/arduino-ide-extension/package.json @@ -91,6 +91,7 @@ "semver": "^7.3.2", "string-natural-compare": "^2.0.3", "temp": "^0.9.1", + "temp-dir": "^2.0.0", "tree-kill": "^1.2.1", "upath": "^1.1.2", "url": "^0.11.0", diff --git a/arduino-ide-extension/src/node/sketches-service-impl.ts b/arduino-ide-extension/src/node/sketches-service-impl.ts index 6725c6933..6598c524d 100644 --- a/arduino-ide-extension/src/node/sketches-service-impl.ts +++ b/arduino-ide-extension/src/node/sketches-service-impl.ts @@ -3,6 +3,7 @@ import * as minimatch from 'minimatch'; import * as fs from 'fs'; import * as os from 'os'; import * as temp from 'temp'; +import * as tempDir from 'temp-dir'; import * as path from 'path'; import * as crypto from 'crypto'; import { ncp } from 'ncp'; @@ -533,8 +534,16 @@ void loop() { } async isTemp(sketch: Sketch): Promise { + // Consider the following paths: + // macOS: + // - Temp folder: /var/folders/k3/d2fkvv1j16v3_rz93k7f74180000gn/T + // - Sketch folder: /private/var/folders/k3/d2fkvv1j16v3_rz93k7f74180000gn/T/arduino-ide2-A0337D47F86B24A51DF3DBCF2CC17925 + // Windows: + // - Temp folder: C:\Users\KITTAA~1\AppData\Local\Temp + // - Sketch folder: c:\Users\kittaakos\AppData\Local\Temp\.arduinoIDE-unsaved2022431-21824-116kfaz.9ljl\sketch_may31a + // Both sketches are valid and temp, but this function will give a false-negative result if we use `os.tmpdir()`. let sketchPath = FileUri.fsPath(sketch.uri); - let temp = await promisify(fs.realpath)(os.tmpdir()); + let temp = tempDir; // https://github.com/sindresorhus/temp-dir // Note: VS Code URI normalizes the drive letter. `C:` will be converted into `c:`. // https://github.com/Microsoft/vscode/issues/68325#issuecomment-462239992 if (isWindows) { @@ -545,7 +554,10 @@ void loop() { temp = firstToLowerCase(temp); } } - return sketchPath.indexOf(prefix) !== -1 && sketchPath.startsWith(temp); + const result = + sketchPath.indexOf(prefix) !== -1 && sketchPath.startsWith(temp); + console.log('isTemp?', result, sketch.uri); + return result; } async copy( diff --git a/yarn.lock b/yarn.lock index d9c93cb5a..610fc73fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14118,6 +14118,11 @@ temp-dir@^1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + temp-write@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-3.4.0.tgz#8cff630fb7e9da05f047c74ce4ce4d685457d492" From ab56005af8a8cdf35de8b9353833265def45d234 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 1 Jun 2022 10:19:56 +0200 Subject: [PATCH 44/45] Relaxed prettier on Windows. Signed-off-by: Akos Kitta --- .prettierrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index b20f01f1c..47e5c04d7 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,5 +2,6 @@ "singleQuote": true, "tabWidth": 2, "useTabs": false, - "printWidth": 80 + "printWidth": 80, + "endOfLine": "auto" } From 8a04d47c29d6cbe6cbb283305a073f0b5d801848 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Wed, 1 Jun 2022 12:18:40 +0200 Subject: [PATCH 45/45] Workaround for non-realpaths on Windows. Signed-off-by: Akos Kitta --- .../src/node/sketches-service-impl.ts | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/arduino-ide-extension/src/node/sketches-service-impl.ts b/arduino-ide-extension/src/node/sketches-service-impl.ts index 6598c524d..e8ac51616 100644 --- a/arduino-ide-extension/src/node/sketches-service-impl.ts +++ b/arduino-ide-extension/src/node/sketches-service-impl.ts @@ -10,7 +10,7 @@ import { ncp } from 'ncp'; import { promisify } from 'util'; import URI from '@theia/core/lib/common/uri'; import { FileUri } from '@theia/core/lib/node'; -import { isWindows } from '@theia/core/lib/common/os'; +import { isWindows, isOSX } from '@theia/core/lib/common/os'; import { ConfigService } from '../common/protocol/config-service'; import { SketchesService, @@ -27,6 +27,7 @@ import { } from './cli-protocol/cc/arduino/cli/commands/v1/commands_pb'; import { duration } from '../common/decorators'; import * as glob from 'glob'; +import { Deferred } from '@theia/core/lib/common/promise-util'; const WIN32_DRIVE_REGEXP = /^[a-zA-Z]:\\/; @@ -39,6 +40,13 @@ export class SketchesServiceImpl { private sketchSuffixIndex = 1; private lastSketchBaseName: string; + // If on macOS, the `temp-dir` lib will make sure there is resolved realpath. + // If on Windows, the `C:\Users\KITTAA~1\AppData\Local\Temp` path will be resolved and normalized to `C:\Users\kittaakos\AppData\Local\Temp`. + // Note: VS Code URI normalizes the drive letter. `C:` will be converted into `c:`. + // https://github.com/Microsoft/vscode/issues/68325#issuecomment-462239992 + private tempDirRealpath = isOSX + ? tempDir + : maybeNormalizeDrive(fs.realpathSync.native(tempDir)); @inject(ConfigService) protected readonly configService: ConfigService; @@ -275,22 +283,39 @@ export class SketchesServiceImpl } async loadSketch(uri: string): Promise { - await this.coreClientProvider.initialized; const { client, instance } = await this.coreClient(); const req = new LoadSketchRequest(); - req.setSketchPath(FileUri.fsPath(uri)); + const requestSketchPath = FileUri.fsPath(uri); + req.setSketchPath(requestSketchPath); req.setInstance(instance); + const stat = new Deferred(); + fs.lstat(requestSketchPath, (err, result) => + err ? stat.resolve(err) : stat.resolve(result) + ); const sketch = await new Promise((resolve, reject) => { client.loadSketch(req, async (err, resp) => { if (err) { reject(err); return; } - const sketchFolderPath = resp.getLocationPath(); - const { mtimeMs } = await promisify(fs.lstat)(sketchFolderPath); + const responseSketchPath = maybeNormalizeDrive(resp.getLocationPath()); + if (requestSketchPath !== responseSketchPath) { + console.warn( + `Warning! The request sketch path was different than the response sketch path from the CLI. This could be a potential bug. Request: <${requestSketchPath}>, response: <${responseSketchPath}>.` + ); + } + const resolvedStat = await stat.promise; + if (resolvedStat instanceof Error) { + console.error( + `The CLI could load the sketch from ${requestSketchPath}, but stating the folder has failed.` + ); + reject(resolvedStat); + return; + } + const { mtimeMs } = resolvedStat; resolve({ - name: path.basename(sketchFolderPath), - uri: FileUri.create(sketchFolderPath).toString(), + name: path.basename(responseSketchPath), + uri: FileUri.create(responseSketchPath).toString(), mainFileUri: FileUri.create(resp.getMainFile()).toString(), otherSketchFileUris: resp .getOtherSketchFilesList() @@ -430,12 +455,18 @@ export class SketchesServiceImpl ]; const today = new Date(); const parentPath = await new Promise((resolve, reject) => { - temp.mkdir({ prefix }, (err, dirPath) => { - if (err) { - reject(err); + temp.mkdir({ prefix }, (createError, dirPath) => { + if (createError) { + reject(createError); return; } - resolve(dirPath); + fs.realpath.native(dirPath, (resolveError, resolvedDirPath) => { + if (resolveError) { + reject(resolveError); + return; + } + resolve(resolvedDirPath); + }); }); }); const sketchBaseName = `sketch_${ @@ -541,21 +572,11 @@ void loop() { // Windows: // - Temp folder: C:\Users\KITTAA~1\AppData\Local\Temp // - Sketch folder: c:\Users\kittaakos\AppData\Local\Temp\.arduinoIDE-unsaved2022431-21824-116kfaz.9ljl\sketch_may31a - // Both sketches are valid and temp, but this function will give a false-negative result if we use `os.tmpdir()`. - let sketchPath = FileUri.fsPath(sketch.uri); - let temp = tempDir; // https://github.com/sindresorhus/temp-dir - // Note: VS Code URI normalizes the drive letter. `C:` will be converted into `c:`. - // https://github.com/Microsoft/vscode/issues/68325#issuecomment-462239992 - if (isWindows) { - if (WIN32_DRIVE_REGEXP.exec(sketchPath)) { - sketchPath = firstToLowerCase(sketchPath); - } - if (WIN32_DRIVE_REGEXP.exec(temp)) { - temp = firstToLowerCase(temp); - } - } + // Both sketches are valid and temp, but this function will give a false-negative result if we use the default `os.tmpdir()` logic. + const sketchPath = maybeNormalizeDrive(FileUri.fsPath(sketch.uri)); + const tempPath = this.tempDirRealpath; // https://github.com/sindresorhus/temp-dir const result = - sketchPath.indexOf(prefix) !== -1 && sketchPath.startsWith(temp); + sketchPath.indexOf(prefix) !== -1 && sketchPath.startsWith(tempPath); console.log('isTemp?', result, sketch.uri); return result; } @@ -667,6 +688,16 @@ interface SketchContainerWithDetails extends SketchContainer { readonly sketches: SketchWithDetails[]; } +/** + * If on Windows, will change the input `C:\\path\\to\\somewhere` to `c:\\path\\to\\somewhere`. + */ +function maybeNormalizeDrive(input: string): string { + if (isWindows && WIN32_DRIVE_REGEXP.test(input)) { + return firstToLowerCase(input); + } + return input; +} + /* * When a new sketch is created, add a suffix to distinguish it * from other new sketches I created today.