diff --git a/demo/src/features/customView.views.ts b/demo/src/features/customView.views.ts index 783d32eb..d24a09bc 100644 --- a/demo/src/features/customView.views.ts +++ b/demo/src/features/customView.views.ts @@ -6,7 +6,6 @@ registerCustomView({ id: 'custom-view', name: 'Custom demo view', order: 0, - default: true, renderBody: function (container: HTMLElement): monaco.IDisposable { container.style.display = 'flex' container.style.alignItems = 'center' diff --git a/demo/src/features/customView.workbench.ts b/demo/src/features/customView.workbench.ts index 1bf38ed3..9134b030 100644 --- a/demo/src/features/customView.workbench.ts +++ b/demo/src/features/customView.workbench.ts @@ -6,7 +6,6 @@ registerCustomView({ id: 'custom-view', name: 'Custom demo view', order: 0, - default: true, renderBody: function (container: HTMLElement): monaco.IDisposable { container.style.display = 'flex' container.style.alignItems = 'center' diff --git a/demo/src/setup.common.ts b/demo/src/setup.common.ts index 8a469439..fdedae5f 100644 --- a/demo/src/setup.common.ts +++ b/demo/src/setup.common.ts @@ -237,7 +237,10 @@ export const constructOptions: IWorkbenchConstructionOptions = { orientation: 0, groups: [{ size: 1 }, { size: 1 }] } - } + }, + views: [{ + id: 'custom-view' + }] }, welcomeBanner: { message: 'Welcome in monaco-vscode-api demo' diff --git a/demo/src/setup.views.ts b/demo/src/setup.views.ts index 8cadd2ec..3951721d 100644 --- a/demo/src/setup.views.ts +++ b/demo/src/setup.views.ts @@ -14,6 +14,7 @@ import getViewsServiceOverride, { Position } from '@codingame/monaco-vscode-views-service-override' import { openNewCodeEditor } from './features/editor' +import './features/customView.views' import { commonServices, constructOptions, remoteAuthority, userDataProvider } from './setup.common' const container = document.createElement('div') diff --git a/demo/src/setup.workbench.ts b/demo/src/setup.workbench.ts index 7f30e0d9..224dbdf6 100644 --- a/demo/src/setup.workbench.ts +++ b/demo/src/setup.workbench.ts @@ -4,6 +4,7 @@ import getQuickAccessServiceOverride from '@codingame/monaco-vscode-quickaccess- import { BrowserStorageService } from '@codingame/monaco-vscode-storage-service-override' import { ExtensionHostKind } from '@codingame/monaco-vscode-extensions-service-override' import { registerExtension } from 'vscode/extensions' +import './features/customView.workbench' import { commonServices, constructOptions, remoteAuthority, userDataProvider } from './setup.common' const container = document.createElement('div') diff --git a/docs/vscode_monaco_upgrade.md b/docs/vscode_monaco_upgrade.md index ab86eb59..1d46d940 100644 --- a/docs/vscode_monaco_upgrade.md +++ b/docs/vscode_monaco_upgrade.md @@ -8,12 +8,11 @@ - Get The tag of the VSCode version from the [VSCode github](https://github.com/microsoft/vscode/tags) - Go to the VSCode repo directory, reset to the previous VSCode tag (`config.vscode.ref` from monaco-vscode-api `package.json`) -- Apply the current patch: `patch -p1 < ../monaco-vscode-api/scripts/vscode.patch` -- `git stash` -- Checkout new VSCode tag -- `git stash pop` +- Apply the current patch: `git am ../monaco-vscode-api/vscode-paches/*.patch` +- Fetch the new tag: `git fetch origin ` +- rebase on the new tag: `git rebase ` - Resolve conflicts / update code (e.g. broken imports) -- Generate new patch: `git diff --staged > ../monaco-vscode-api/scripts/vscode.patch` +- Generate new patch: `rm -rf ../monaco-vscode-api/vscode-paches && git format-patch .. -o '../monaco-vscode-api/vscode-paches'` ## monaco-vscode-api repository diff --git a/scripts/install-vscode b/scripts/install-vscode index 5926a40d..c917906e 100755 --- a/scripts/install-vscode +++ b/scripts/install-vscode @@ -7,7 +7,7 @@ output_directory="`pwd`/vscode" loc_output_directory="`pwd`/vscode-loc" extension_output_directory="`pwd`/vscode-default-extensions" extension_node_output_directory="`pwd`/vscode-default-extensions-node" -patch_file="`pwd`/scripts/vscode.patch" +patch_directory="`pwd`/vscode-paches" version_info=$output_directory/version.info if [[ -e $version_info && $(cat $version_info) == $vscodeRef ]]; then @@ -34,7 +34,7 @@ yarn install --ignore-scripts yarn postinstall || true echo "Patching vscode..." -patch -p1 < $patch_file +find "$patch_directory" -type f -name '*.patch' -print0 | sort -z | xargs -t -0 -n 1 patch -p1 -i echo "Installing build dependencies" cd build diff --git a/scripts/vscode.patch b/scripts/vscode.patch deleted file mode 100644 index f56f0148..00000000 --- a/scripts/vscode.patch +++ /dev/null @@ -1,6388 +0,0 @@ -diff --git a/.eslintrc.json b/.eslintrc.json -index 0922babfe92..59769eeda54 100644 ---- a/.eslintrc.json -+++ b/.eslintrc.json -@@ -671,6 +671,7 @@ - "v8-inspect-profiler", - "vscode-regexpp", - "vscode-textmate", -+ "vscode-oniguruma", - "worker_threads", - "@xterm/addon-canvas", - "@xterm/addon-image", -diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js -index 22b70a953df..4c92c45941a 100644 ---- a/build/gulpfile.editor.js -+++ b/build/gulpfile.editor.js -@@ -277,7 +277,16 @@ function toExternalDTS(contents) { - } - - if (line.indexOf('declare let MonacoEnvironment') === 0) { -- lines[i] = `declare global {\n let MonacoEnvironment: Environment | undefined;\n}`; -+ lines[i] = [ -+ 'declare global {', -+ ' let MonacoEnvironment: Environment | undefined;', -+ '', -+ ' interface Window {', -+ ' MonacoEnvironment?: Environment | undefined;', -+ ' }', -+ '}', -+ '' -+ ].join('\n'); - } - - if (line.indexOf('\tMonacoEnvironment?') === 0) { -@@ -404,17 +413,10 @@ gulp.task('editor-distro', - util.rimraf('out-editor-min') - ), - extractEditorSrcTask, -- task.parallel( -- task.series( -- compileEditorAMDTask, -- optimizeEditorAMDTask, -- minifyEditorAMDTask -- ), -- task.series( -- createESMSourcesAndResourcesTask, -- compileEditorESMTask, -- appendJSToESMImportsTask -- ) -+ task.series( -+ createESMSourcesAndResourcesTask, -+ compileEditorESMTask, -+ appendJSToESMImportsTask - ), - finalEditorResourcesTask - ) -diff --git a/build/lib/standalone.js b/build/lib/standalone.js -index 4ddf88ed223..ddb16108fda 100644 ---- a/build/lib/standalone.js -+++ b/build/lib/standalone.js -@@ -134,7 +134,7 @@ function createESMSourcesAndResources2(options) { - } - if (file === 'tsconfig.json') { - const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); -- tsConfig.compilerOptions.module = 'es6'; -+ tsConfig.compilerOptions.module = 'es2020'; - tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/'); - write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); - continue; -@@ -150,6 +150,9 @@ function createESMSourcesAndResources2(options) { - const info = ts.preProcessFile(fileContents); - for (let i = info.importedFiles.length - 1; i >= 0; i--) { - const importedFilename = info.importedFiles[i].fileName; -+ if (!importedFilename.startsWith('vs/')) { -+ continue; -+ } - const pos = info.importedFiles[i].pos; - const end = info.importedFiles[i].end; - let importedFilepath; -@@ -172,6 +175,10 @@ function createESMSourcesAndResources2(options) { - else { - relativePath = path.relative(path.dirname(file), importedFilepath); - } -+ if (relativePath.endsWith('..')) { -+ // When a folder have the same name as a file -+ relativePath = relativePath + '/../' + path.basename(importedFilepath); -+ } - relativePath = relativePath.replace(/\\/g, '/'); - if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { - relativePath = './' + relativePath; -@@ -183,6 +190,13 @@ function createESMSourcesAndResources2(options) { - fileContents = fileContents.replace(/import ([a-zA-Z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { - return `import * as ${m1} from ${m2};`; - }); -+ if (!file.includes('vs/nls')) { -+ fileContents = fileContents.replace(/\b(localize2?)\(/g, function (_, name) { -+ return `${name}WithPath('${file.slice(0, -3)}', `; -+ }); -+ } -+ fileContents = fileContents.replace(/import { (localize2?) }/g, 'import { $1WithPath }'); -+ fileContents = fileContents.replace(/import { localize, localize2 }/g, 'import { localizeWithPath, localize2WithPath }'); - write(getDestAbsoluteFilePath(file), fileContents); - continue; - } -diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts -index 775a1be5996..224f376d4bf 100644 ---- a/build/lib/standalone.ts -+++ b/build/lib/standalone.ts -@@ -160,7 +160,7 @@ export function createESMSourcesAndResources2(options: IOptions2): void { - - if (file === 'tsconfig.json') { - const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); -- tsConfig.compilerOptions.module = 'es6'; -+ tsConfig.compilerOptions.module = 'es2020'; - tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/'); - write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); - continue; -@@ -180,6 +180,9 @@ export function createESMSourcesAndResources2(options: IOptions2): void { - - for (let i = info.importedFiles.length - 1; i >= 0; i--) { - const importedFilename = info.importedFiles[i].fileName; -+ if (!importedFilename.startsWith('vs/')) { -+ continue; -+ } - const pos = info.importedFiles[i].pos; - const end = info.importedFiles[i].end; - -@@ -201,6 +204,10 @@ export function createESMSourcesAndResources2(options: IOptions2): void { - } else { - relativePath = path.relative(path.dirname(file), importedFilepath); - } -+ if (relativePath.endsWith('..')) { -+ // When a folder have the same name as a file -+ relativePath = relativePath + '/../' + path.basename(importedFilepath); -+ } - relativePath = relativePath.replace(/\\/g, '/'); - if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { - relativePath = './' + relativePath; -@@ -216,6 +223,14 @@ export function createESMSourcesAndResources2(options: IOptions2): void { - return `import * as ${m1} from ${m2};`; - }); - -+ if (!file.includes('vs/nls')) { -+ fileContents = fileContents.replace(/\b(localize2?)\(/g, function (_, name) { -+ return `${name}WithPath('${file.slice(0, -3)}', `; -+ }); -+ } -+ fileContents = fileContents.replace(/import { (localize2?) }/g, 'import { $1WithPath }'); -+ fileContents = fileContents.replace(/import { localize, localize2 }/g, 'import { localizeWithPath, localize2WithPath }'); -+ - write(getDestAbsoluteFilePath(file), fileContents); - continue; - } -diff --git a/extensions/markdown-language-features/src/extension.browser.ts b/extensions/markdown-language-features/src/extension.browser.ts -index 30639672490..2095905a4d8 100644 ---- a/extensions/markdown-language-features/src/extension.browser.ts -+++ b/extensions/markdown-language-features/src/extension.browser.ts -@@ -30,7 +30,7 @@ function startServer(context: vscode.ExtensionContext, parser: IMdParser): Promi - const serverMain = vscode.Uri.joinPath(context.extensionUri, 'server/dist/browser/workerMain.js'); - - const worker = new Worker(serverMain.toString()); -- worker.postMessage({ i10lLocation: vscode.l10n.uri?.toString() ?? '' }); -+ worker.postMessage({ i10lLocation: vscode.l10n.uri?.toString(true) ?? '' }); - - return startClient((id: string, name: string, clientOptions: LanguageClientOptions) => { - return new LanguageClient(id, name, clientOptions, worker); -diff --git a/extensions/typescript-language-features/web/src/pathMapper.ts b/extensions/typescript-language-features/web/src/pathMapper.ts -index e92548950fc..a0c2c248f96 100644 ---- a/extensions/typescript-language-features/web/src/pathMapper.ts -+++ b/extensions/typescript-language-features/web/src/pathMapper.ts -@@ -20,7 +20,7 @@ export class PathMapper { - return URI.from({ - scheme: this.extensionUri.scheme, - authority: this.extensionUri.authority, -- path: this.extensionUri.path + '/dist/browser/typescript/' + filepath.slice(1) -+ path: this.extensionUri.path.replace(/\/$/, '') + '/dist/browser/typescript/' + filepath.slice(1) - }); - } - -@@ -76,7 +76,7 @@ export function fromResource(extensionUri: URI, uri: URI) { - && uri.path.endsWith('.d.ts')) { - return uri.path; - } -- return `/${uri.scheme}/${uri.authority}${uri.path}`; -+ return `/${uri.scheme}/${uri.authority || 'ts-nul-authority'}${uri.path}`; - } - - export function looksLikeLibDtsPath(filepath: string) { -diff --git a/extensions/typescript-language-features/web/src/serverHost.ts b/extensions/typescript-language-features/web/src/serverHost.ts -index f2f9ca95996..f5c28ec0cab 100644 ---- a/extensions/typescript-language-features/web/src/serverHost.ts -+++ b/extensions/typescript-language-features/web/src/serverHost.ts -@@ -88,7 +88,7 @@ function createServerHost( - - const scriptPath = combinePaths(packageRoot, browser); - try { -- const { default: module } = await import(/* webpackIgnore: true */ scriptPath); -+ const { default: module } = await new Function('url', 'return importExt(url)')(scriptPath); - return { module, error: undefined }; - } catch (e) { - return { module: undefined, error: e }; -diff --git a/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts b/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts -index 7c40993d6df..4f3893aa7c6 100644 ---- a/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts -+++ b/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts -@@ -66,7 +66,9 @@ export class WebTypingsInstallerClient implements ts.server.ITypingsInstaller { - case 'action::packageInstalled': - case 'action::invalidate': - case 'action::set': -- this.projectService!.updateTypingsForProject(response); -+ // missing case leads to error -+ case 'action::watchTypingLocations': -+ this.projectService!.updateTypingsForProject(response as any); - break; - case 'event::beginInstallTypes': - case 'event::endInstallTypes': -diff --git a/src/tsconfig.base.json b/src/tsconfig.base.json -index c0a2e174591..1d80c22afa3 100644 ---- a/src/tsconfig.base.json -+++ b/src/tsconfig.base.json -@@ -1,6 +1,7 @@ - { - "compilerOptions": { -- "module": "amd", -+ "esModuleInterop": true, -+ "module": "ES2020", - "moduleResolution": "node", - "experimentalDecorators": true, - "noImplicitReturns": true, -diff --git a/src/tsconfig.monaco.json b/src/tsconfig.monaco.json -index 988f0485713..c73b524ea2a 100644 ---- a/src/tsconfig.monaco.json -+++ b/src/tsconfig.monaco.json -@@ -7,11 +7,11 @@ - "wicg-file-system-access" - ], - "paths": {}, -- "module": "amd", -+ "module": "es2020", - "moduleResolution": "classic", - "removeComments": false, - "preserveConstEnums": true, -- "target": "es2018", -+ "target": "es2020", - "sourceMap": false, - "declaration": true - }, -diff --git a/src/vs/base/browser/defaultWorkerFactory.ts b/src/vs/base/browser/defaultWorkerFactory.ts -index 71391b063f3..7878de1cbfa 100644 ---- a/src/vs/base/browser/defaultWorkerFactory.ts -+++ b/src/vs/base/browser/defaultWorkerFactory.ts -@@ -5,7 +5,9 @@ - - import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes'; - import { onUnexpectedError } from 'vs/base/common/errors'; -+// ESM-comment-begin - import { COI } from 'vs/base/common/network'; -+// ESM-comment-end - import { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker'; - import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; - -diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.css b/src/vs/base/browser/ui/codicons/codicon/codicon.css -index 02154e77b68..d7f257db934 100644 ---- a/src/vs/base/browser/ui/codicons/codicon/codicon.css -+++ b/src/vs/base/browser/ui/codicons/codicon/codicon.css -@@ -6,7 +6,7 @@ - @font-face { - font-family: "codicon"; - font-display: block; -- src: url("./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6") format("truetype"); -+ src: url("./codicon.ttf") format("truetype"); - } - - .codicon[class*='codicon-'] { -diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts -index 974d0c21743..aae916fa686 100644 ---- a/src/vs/base/common/network.ts -+++ b/src/vs/base/common/network.ts -@@ -4,6 +4,8 @@ - *--------------------------------------------------------------------------------------------*/ - - import * as errors from 'vs/base/common/errors'; -+import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -+import { ResourceMap } from 'vs/base/common/map'; - import * as platform from 'vs/base/common/platform'; - import { equalsIgnoreCase, startsWithIgnoreCase } from 'vs/base/common/strings'; - import { URI } from 'vs/base/common/uri'; -@@ -223,6 +225,30 @@ export const VSCODE_AUTHORITY = 'vscode-app'; - class FileAccessImpl { - - private static readonly FALLBACK_AUTHORITY = VSCODE_AUTHORITY; -+ private staticBrowserUris = new ResourceMap(); -+ private appResourcePathUrls = new Map string)>(); -+ -+ private moduleContentProvider = new Map Promise>(); -+ -+ public registerModuleContentProvider(moduleId: string, contentLoader: () => Promise) { -+ this.moduleContentProvider.set(moduleId, contentLoader); -+ } -+ -+ public toModuleContent(moduleId: string): Promise { -+ return this.moduleContentProvider.get(moduleId)!(); -+ } -+ -+ public registerAppResourcePathUrl(moduleId: string, url: string | (() => string)): void { -+ this.appResourcePathUrls.set(moduleId, url); -+ } -+ -+ private toUrl(moduleId: string): string { -+ let url = this.appResourcePathUrls.get(moduleId); -+ if (typeof url === 'function') { -+ url = url(); -+ } -+ return new URL(url ?? moduleId, globalThis.location?.href ?? import.meta.url).toString(); -+ } - - /** - * Returns a URI to use in contexts where the browser is responsible -@@ -231,7 +257,7 @@ class FileAccessImpl { - * **Note:** use `dom.ts#asCSSUrl` whenever the URL is to be used in CSS context. - */ - asBrowserUri(resourcePath: AppResourcePath | ''): URI { -- const uri = this.toUri(resourcePath, require); -+ const uri = this.toUri(resourcePath, { toUrl: this.toUrl.bind(this) }); - return this.uriToBrowserUri(uri); - } - -@@ -270,7 +296,7 @@ class FileAccessImpl { - }); - } - -- return uri; -+ return this.staticBrowserUris.get(uri) ?? uri; - } - - /** -@@ -278,7 +304,7 @@ class FileAccessImpl { - * is responsible for loading. - */ - asFileUri(resourcePath: AppResourcePath | ''): URI { -- const uri = this.toUri(resourcePath, require); -+ const uri = this.toUri(resourcePath, { toUrl: this.toUrl.bind(this) }); - return this.uriToFileUri(uri); - } - -@@ -310,6 +336,19 @@ class FileAccessImpl { - - return URI.parse(moduleIdToUrl.toUrl(uriOrModule)); - } -+ -+ registerStaticBrowserUri(uri: URI, browserUri: URI): IDisposable { -+ this.staticBrowserUris.set(uri, browserUri); -+ return toDisposable(() => { -+ if (this.staticBrowserUris.get(uri) === browserUri) { -+ this.staticBrowserUris.delete(uri); -+ } -+ }); -+ } -+ -+ getRegisteredBrowserUris(): IterableIterator { -+ return this.staticBrowserUris.keys(); -+ } - } - - export const FileAccess = new FileAccessImpl(); -diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js -index aff4d0734de..ea43e4a2fcc 100644 ---- a/src/vs/base/common/performance.js -+++ b/src/vs/base/common/performance.js -@@ -6,7 +6,7 @@ - 'use strict'; - - //@ts-check -- -+// ESM-comment-begin - (function () { - - /** -@@ -123,3 +123,27 @@ - } - - })(); -+// ESM-comment-end -+ -+// ESM-uncomment-begin -+// export const mark = (name) => { -+// performance.mark(name); -+// }; -+ -+// export const getMarks = () => { -+// let timeOrigin = performance.timeOrigin; -+// if (typeof timeOrigin !== 'number') { -+// // safari: there is no timerOrigin but in renderers there is the timing-property -+// // see https://bugs.webkit.org/show_bug.cgi?id=174862 -+// timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart; -+// } -+// const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }]; -+// for (const entry of performance.getEntriesByType('mark')) { -+// result.push({ -+// name: entry.name, -+// startTime: Math.round(timeOrigin + entry.startTime) -+// }); -+// } -+// return result; -+// }; -+// ESM-uncomment-end -diff --git a/src/vs/editor/browser/config/editorConfiguration.ts b/src/vs/editor/browser/config/editorConfiguration.ts -index 06e8339cbc7..799c2f81cd0 100644 ---- a/src/vs/editor/browser/config/editorConfiguration.ts -+++ b/src/vs/editor/browser/config/editorConfiguration.ts -@@ -43,6 +43,7 @@ export class EditorConfiguration extends Disposable implements IEditorConfigurat - public readonly onDidChangeFast: Event = this._onDidChangeFast.event; - - public readonly isSimpleWidget: boolean; -+ public readonly isStandaloneEditor: boolean; - private readonly _containerObserver: ElementSizeObserver; - - private _isDominatedByLongLines: boolean = false; -@@ -68,12 +69,14 @@ export class EditorConfiguration extends Disposable implements IEditorConfigurat - - constructor( - isSimpleWidget: boolean, -+ isStandaloneEditor: boolean, - options: Readonly, - container: HTMLElement | null, - @IAccessibilityService private readonly _accessibilityService: IAccessibilityService - ) { - super(); - this.isSimpleWidget = isSimpleWidget; -+ this.isStandaloneEditor = isStandaloneEditor; - this._containerObserver = this._register(new ElementSizeObserver(container, options.dimension)); - this._targetWindowId = getWindow(container).vscodeWindowId; - -@@ -130,7 +133,7 @@ export class EditorConfiguration extends Disposable implements IEditorConfigurat - - protected _readEnvConfiguration(): IEnvConfiguration { - return { -- extraEditorClassName: getExtraEditorClassName(), -+ extraEditorClassName: getExtraEditorClassName(this.isStandaloneEditor), - outerWidth: this._containerObserver.getWidth(), - outerHeight: this._containerObserver.getHeight(), - emptySelectionClipboard: browser.isWebKit || browser.isFirefox, -@@ -218,7 +221,7 @@ function digitCount(n: number): number { - return r ? r : 1; - } - --function getExtraEditorClassName(): string { -+function getExtraEditorClassName(isStandaloneEditor: boolean): string { - let extra = ''; - if (!browser.isSafari && !browser.isWebkitWebView) { - // Use user-select: none in all browsers except Safari and native macOS WebView -@@ -232,6 +235,9 @@ function getExtraEditorClassName(): string { - if (platform.isMacintosh) { - extra += 'mac '; - } -+ if (isStandaloneEditor) { -+ extra += 'standalone '; -+ } - return extra; - } - -@@ -273,7 +279,7 @@ export class ComputedEditorOptions implements IComputedEditorOptions { - } - } - --class EditorOptionsUtil { -+export class EditorOptionsUtil { - - public static validateOptions(options: IEditorOptions): ValidatedEditorOptions { - const result = new ValidatedEditorOptions(); -diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts -index 5466f913d24..d8dfad03a43 100644 ---- a/src/vs/editor/browser/widget/codeEditorWidget.ts -+++ b/src/vs/editor/browser/widget/codeEditorWidget.ts -@@ -70,6 +70,12 @@ export interface ICodeEditorWidgetOptions { - */ - isSimpleWidget?: boolean; - -+ /** -+ * Is this a standalone editor -+ * Defaults to false. -+ */ -+ isStandaloneEditor?: boolean; -+ - /** - * Contributions to instantiate. - * When provided, only the contributions included will be instantiated. -@@ -300,7 +306,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE - this._decorationTypeSubtypes = {}; - this._telemetryData = codeEditorWidgetOptions.telemetryData; - -- this._configuration = this._register(this._createConfiguration(codeEditorWidgetOptions.isSimpleWidget || false, options, accessibilityService)); -+ this._configuration = this._register(this._createConfiguration(codeEditorWidgetOptions.isSimpleWidget || false, codeEditorWidgetOptions.isStandaloneEditor || false, options, accessibilityService)); - this._register(this._configuration.onDidChange((e) => { - this._onDidChangeConfiguration.fire(e); - -@@ -408,8 +414,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE - this._modelData?.view.writeScreenReaderContent(reason); - } - -- protected _createConfiguration(isSimpleWidget: boolean, options: Readonly, accessibilityService: IAccessibilityService): EditorConfiguration { -- return new EditorConfiguration(isSimpleWidget, options, this._domElement, accessibilityService); -+ protected _createConfiguration(isSimpleWidget: boolean, isStandaloneEditor: boolean, options: Readonly, accessibilityService: IAccessibilityService): EditorConfiguration { -+ return new EditorConfiguration(isSimpleWidget, isStandaloneEditor, options, this._domElement, accessibilityService); - } - - public getId(): string { -diff --git a/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts -index 6b57de66397..67837f9885e 100644 ---- a/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts -+++ b/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts -@@ -49,6 +49,12 @@ import { RevertButtonsFeature } from 'vs/editor/browser/widget/diffEditor/featur - export interface IDiffCodeEditorWidgetOptions { - originalEditor?: ICodeEditorWidgetOptions; - modifiedEditor?: ICodeEditorWidgetOptions; -+ -+ /** -+ * Is this a standalone editor -+ * Defaults to false. -+ */ -+ isStandaloneEditor?: boolean; - } - - export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor { -@@ -105,6 +111,8 @@ export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor { - - this._contextKeyService.createKey('isInDiffEditor', true); - -+ this.elements.root.classList.toggle('standalone', codeEditorWidgetOptions.isStandaloneEditor || false); -+ - this._domElement.appendChild(this.elements.root); - this._register(toDisposable(() => this._domElement.removeChild(this.elements.root))); - -diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts -index bd51c9ec27d..7e818a253d4 100644 ---- a/src/vs/editor/common/config/editorOptions.ts -+++ b/src/vs/editor/common/config/editorOptions.ts -@@ -858,6 +858,7 @@ export interface IDiffEditorBaseOptions { - minimumLineCount?: number; - contextLineCount?: number; - }; -+ - } - - /** -diff --git a/src/vs/editor/standalone/browser/standalone-tokens.css b/src/vs/editor/standalone/browser/standalone-tokens.css -index 1fc85078f9e..c74aca00541 100644 ---- a/src/vs/editor/standalone/browser/standalone-tokens.css -+++ b/src/vs/editor/standalone/browser/standalone-tokens.css -@@ -5,7 +5,7 @@ - - - /* Default standalone editor fonts */ --.monaco-editor { -+.monaco-editor.standalone { - font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", system-ui, "Ubuntu", "Droid Sans", sans-serif; - --monaco-monospace-font: "SF Mono", Monaco, Menlo, Consolas, "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace; - } -@@ -14,9 +14,9 @@ - stroke-width: 1.2px; - } - --.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, --.monaco-editor.hc-black .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, --.monaco-editor.hc-light .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label { -+.monaco-editor.standalone.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, -+.monaco-editor.standalone.hc-black .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, -+.monaco-editor.standalone.hc-light .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label { - stroke-width: 1.2px; - } - -@@ -37,16 +37,16 @@ - clip-path: inset(50%); - } - --.monaco-editor, .monaco-diff-editor .synthetic-focus, --.monaco-editor, .monaco-diff-editor [tabindex="0"]:focus, --.monaco-editor, .monaco-diff-editor [tabindex="-1"]:focus, --.monaco-editor, .monaco-diff-editor button:focus, --.monaco-editor, .monaco-diff-editor input[type=button]:focus, --.monaco-editor, .monaco-diff-editor input[type=checkbox]:focus, --.monaco-editor, .monaco-diff-editor input[type=search]:focus, --.monaco-editor, .monaco-diff-editor input[type=text]:focus, --.monaco-editor, .monaco-diff-editor select:focus, --.monaco-editor, .monaco-diff-editor textarea:focus { -+.monaco-editor.standalone, .monaco-diff-editor.standalone .synthetic-focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone [tabindex="0"]:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone [tabindex="-1"]:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone button:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=button]:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=checkbox]:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=search]:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=text]:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone select:focus, -+.monaco-editor.standalone, .monaco-diff-editor.standalone textarea:focus { - outline-width: 1px; - outline-style: solid; - outline-offset: -1px; -diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts -index 479bb75745c..f5b5da97a2c 100644 ---- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts -+++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts -@@ -282,7 +282,7 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon - const options = { ..._options }; - options.ariaLabel = options.ariaLabel || StandaloneCodeEditorNLS.editorViewAccessibleLabel; - options.ariaLabel = options.ariaLabel + ';' + (StandaloneCodeEditorNLS.accessibilityHelpMessage); -- super(domElement, options, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService); -+ super(domElement, options, { isStandaloneEditor: true }, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService); - - if (keybindingService instanceof StandaloneKeybindingService) { - this._standaloneKeybindingService = keybindingService; -@@ -518,7 +518,7 @@ export class StandaloneDiffEditor2 extends DiffEditorWidget implements IStandalo - super( - domElement, - options, -- {}, -+ { isStandaloneEditor: true }, - contextKeyService, - instantiationService, - codeEditorService, -diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts -index 351f85537d8..d6995d24729 100644 ---- a/src/vs/editor/standalone/browser/standaloneServices.ts -+++ b/src/vs/editor/standalone/browser/standaloneServices.ts -@@ -90,8 +90,6 @@ import { DefaultConfiguration } from 'vs/platform/configuration/common/configura - import { WorkspaceEdit } from 'vs/editor/common/languages'; - import { AccessibilitySignal, IAccessibilitySignalService, Sound } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService'; - import { LogService } from 'vs/platform/log/common/logService'; --import { getEditorFeatures } from 'vs/editor/common/editorFeatures'; --import { onUnexpectedError } from 'vs/base/common/errors'; - import { ExtensionKind, IEnvironmentService, IExtensionHostDebugParams } from 'vs/platform/environment/common/environment'; - import { mainWindow } from 'vs/base/browser/window'; - -@@ -525,15 +523,19 @@ export class StandaloneKeybindingService extends AbstractKeybindingService { - }); - } - -- private updateResolver(): void { -+ protected updateResolver(): void { - this._cachedResolver = null; - this._onDidUpdateKeybindings.fire(); - } - -+ protected getUserKeybindingItems() { -+ return this._toNormalizedKeybindingItems(this._dynamicKeybindings, false); -+ } -+ - protected _getResolver(): KeybindingResolver { - if (!this._cachedResolver) { - const defaults = this._toNormalizedKeybindingItems(KeybindingsRegistry.getDefaultKeybindings(), true); -- const overrides = this._toNormalizedKeybindingItems(this._dynamicKeybindings, false); -+ const overrides = this.getUserKeybindingItems(); - this._cachedResolver = new KeybindingResolver(defaults, overrides, (str) => this._log(str)); - } - return this._cachedResolver; -@@ -554,7 +556,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService { - // This might be a removal keybinding item in user settings => accept it - result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, null, false); - } else { -- const resolvedKeybindings = USLayoutResolvedKeybinding.resolveKeybinding(keybinding, OS); -+ const resolvedKeybindings = this.resolveKeybinding(keybinding); - for (const resolvedKeybinding of resolvedKeybindings) { - result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, null, false); - } -@@ -1183,16 +1185,6 @@ export module StandaloneServices { - } - } - -- // Instantiate all editor features -- const editorFeatures = getEditorFeatures(); -- for (const feature of editorFeatures) { -- try { -- instantiationService.createInstance(feature); -- } catch (err) { -- onUnexpectedError(err); -- } -- } -- - onDidInitialize.fire(); - - return instantiationService; -diff --git a/src/vs/editor/test/browser/config/testConfiguration.ts b/src/vs/editor/test/browser/config/testConfiguration.ts -index b5d42908ded..3815f8fb823 100644 ---- a/src/vs/editor/test/browser/config/testConfiguration.ts -+++ b/src/vs/editor/test/browser/config/testConfiguration.ts -@@ -13,7 +13,7 @@ import { TestAccessibilityService } from 'vs/platform/accessibility/test/common/ - export class TestConfiguration extends EditorConfiguration { - - constructor(opts: Readonly) { -- super(false, opts, null, new TestAccessibilityService()); -+ super(false, false, opts, null, new TestAccessibilityService()); - } - - protected override _readEnvConfiguration(): IEnvConfiguration { -diff --git a/src/vs/editor/test/browser/testCodeEditor.ts b/src/vs/editor/test/browser/testCodeEditor.ts -index b29e05c8053..f941b3a248f 100644 ---- a/src/vs/editor/test/browser/testCodeEditor.ts -+++ b/src/vs/editor/test/browser/testCodeEditor.ts -@@ -68,7 +68,7 @@ export interface ITestCodeEditor extends IActiveCodeEditor { - export class TestCodeEditor extends CodeEditorWidget implements ICodeEditor { - - //#region testing overrides -- protected override _createConfiguration(isSimpleWidget: boolean, options: Readonly): EditorConfiguration { -+ protected override _createConfiguration(isSimpleWidget: boolean, isStandaloneEditor: boolean, options: Readonly): EditorConfiguration { - return new TestConfiguration(options); - } - protected override _createView(viewModel: ViewModel): [View, boolean] { -diff --git a/src/vs/nls.ts b/src/vs/nls.ts -index 233840e65ab..ff3661e3472 100644 ---- a/src/vs/nls.ts -+++ b/src/vs/nls.ts -@@ -164,6 +164,35 @@ export function localize(data: ILocalizeInfo | string, message: string, ...args: - return _format(message, args); - } - -+let locale: string | undefined = undefined; -+let translations: Record> = {}; -+ -+export function setLocale(_locale: string, _translations: Record>) { -+ locale = _locale; -+ translations = _translations; -+} -+ -+/** -+ * @skipMangle -+ */ -+export function localizeWithPath(path: string, data: ILocalizeInfo | string, defaultMessage: string, ...args: (string | number | boolean | undefined | null)[]): string { -+ const key = typeof data === 'object' ? data.key : data; -+ const message = (translations[path] ?? {})[key] ?? defaultMessage; -+ return _format(message, args); -+} -+ -+/** -+ * @skipMangle -+ */ -+export function localize2WithPath(path: string, data: ILocalizeInfo | string, defaultMessage: string, ...args: (string | number | boolean | undefined | null)[]): ILocalizedString { -+ const key = typeof data === 'object' ? data.key : data; -+ const message = (translations[path] ?? {})[key] ?? defaultMessage; -+ return { -+ value: _format(message, args), -+ original: _format(defaultMessage, args) -+ }; -+} -+ - /** - * Marks a string to be localized. Returns an {@linkcode ILocalizedString} - * which contains the localized string and the original string. -@@ -217,7 +246,7 @@ export function getConfiguredDefaultLocale(stringFromLocalizeCall: string): stri - export function getConfiguredDefaultLocale(_: string): string | undefined { - // This returns undefined because this implementation isn't used and is overwritten by the loader - // when loaded. -- return undefined; -+ return locale; - } - - /** -diff --git a/src/vs/platform/assignment/common/assignmentService.ts b/src/vs/platform/assignment/common/assignmentService.ts -index c573b727e0b..8c52126a590 100644 ---- a/src/vs/platform/assignment/common/assignmentService.ts -+++ b/src/vs/platform/assignment/common/assignmentService.ts -@@ -9,7 +9,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur - import { IProductService } from 'vs/platform/product/common/productService'; - import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils'; - import { AssignmentFilterProvider, ASSIGNMENT_REFETCH_INTERVAL, ASSIGNMENT_STORAGE_KEY, IAssignmentService, TargetPopulation } from 'vs/platform/assignment/common/assignment'; --import { importAMDNodeModule } from 'vs/amdX'; - import { IEnvironmentService } from 'vs/platform/environment/common/environment'; - - export abstract class BaseAssignmentService implements IAssignmentService { -@@ -88,7 +87,7 @@ export abstract class BaseAssignmentService implements IAssignmentService { - ); - - const tasConfig = this.productService.tasConfig!; -- const tasClient = new (await importAMDNodeModule('tas-client-umd', 'lib/tas-client-umd.js')).ExperimentationService({ -+ const tasClient = new (await import('tas-client-umd')).ExperimentationService({ - filterProviders: [filterProvider], - telemetry: this.telemetry, - storageKey: ASSIGNMENT_STORAGE_KEY, -diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts -index 0d3a9795ffb..2cc1981808a 100644 ---- a/src/vs/platform/environment/node/argv.ts -+++ b/src/vs/platform/environment/node/argv.ts -@@ -3,7 +3,7 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import * as minimist from 'minimist'; -+import minimist from 'minimist'; - import { isWindows } from 'vs/base/common/platform'; - import { localize } from 'vs/nls'; - import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -diff --git a/src/vs/platform/environment/node/argvHelper.ts b/src/vs/platform/environment/node/argvHelper.ts -index d8cefb6df67..a94fca911ea 100644 ---- a/src/vs/platform/environment/node/argvHelper.ts -+++ b/src/vs/platform/environment/node/argvHelper.ts -@@ -3,7 +3,7 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import * as assert from 'assert'; -+import assert from 'assert'; - import { IProcessEnvironment } from 'vs/base/common/platform'; - import { localize } from 'vs/nls'; - import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -diff --git a/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts b/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts -index fdefc170db0..1d3bc4affc5 100644 ---- a/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts -+++ b/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts -@@ -14,7 +14,7 @@ import { ILogService } from 'vs/platform/log/common/log'; - import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; - import { AbstractExtensionResourceLoaderService, IExtensionResourceLoaderService } from 'vs/platform/extensionResourceLoader/common/extensionResourceLoader'; - --class ExtensionResourceLoaderService extends AbstractExtensionResourceLoaderService { -+export class ExtensionResourceLoaderService extends AbstractExtensionResourceLoaderService { - - declare readonly _serviceBrand: undefined; - -diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts -index 413c1db06f1..c1667ac6c33 100644 ---- a/src/vs/platform/extensions/common/extensions.ts -+++ b/src/vs/platform/extensions/common/extensions.ts -@@ -3,6 +3,7 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -+import { IJSONSchema } from 'vs/base/common/jsonSchema'; - import Severity from 'vs/base/common/severity'; - import * as strings from 'vs/base/common/strings'; - import { URI } from 'vs/base/common/uri'; -@@ -16,110 +17,496 @@ export const BUILTIN_MANIFEST_CACHE_FILE = 'extensions.builtin.cache'; - export const UNDEFINED_PUBLISHER = 'undefined_publisher'; - - export interface ICommand { -- command: string; -- title: string | ILocalizedString; -- category?: string | ILocalizedString; --} -- --export interface IConfigurationProperty { -- description: string; -- type: string | string[]; -- default?: any; -+ /** -+ * Identifier of the command to execute -+ */ -+ readonly command: string; -+ /** -+ * Title by which the command is represented in the UI -+ */ -+ readonly title: string | ILocalizedString; -+ readonly shortTitle?: string; -+ /** -+ * (Optional) Category string by which the command is grouped in the UI -+ */ -+ readonly category?: string | ILocalizedString; -+ /** -+ * (Optional) Condition which must be true to enable the command in the UI (menu and keybindings). Does not prevent executing the command by other means, like the `executeCommand`-api. -+ */ -+ readonly enablement?: string; -+ /** -+ * (Optional) Icon which is used to represent the command in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `\$(zap)` -+ */ -+ readonly icon?: -+ | string -+ | { -+ /** -+ * Icon path when a light theme is used -+ */ -+ readonly light?: string; -+ /** -+ * Icon path when a dark theme is used -+ */ -+ readonly dark?: string; -+ }; - } - - export interface IConfiguration { -- id?: string; -- order?: number; -- title?: string; -- properties: { [key: string]: IConfigurationProperty }; -+ /** -+ * A title for the current category of settings. This label will be rendered in the Settings editor as a subheading. If the title is the same as the extension display name, then the category will be grouped under the main extension heading. -+ */ -+ readonly title?: string; -+ /** -+ * When specified, gives the order of this category of settings relative to other categories. -+ */ -+ readonly order?: number; -+ /** -+ * Description of the configuration properties. -+ */ -+ readonly properties: { [key: string]: IJSONSchema }; - } - - export interface IDebugger { -- label?: string; -- type: string; -- runtime?: string; -+ /** -+ * Unique identifier for this debug adapter. -+ */ -+ readonly type: string; -+ /** -+ * Display name for this debug adapter. -+ */ -+ readonly label?: string; -+ /** -+ * Path to the debug adapter program. Path is either absolute or relative to the extension folder. -+ */ -+ readonly program?: string; -+ /** -+ * Optional arguments to pass to the adapter. -+ */ -+ readonly args?: unknown[]; -+ /** -+ * Optional runtime in case the program attribute is not an executable but requires a runtime. -+ */ -+ readonly runtime?: string; -+ /** -+ * Optional runtime arguments. -+ */ -+ readonly runtimeArgs?: unknown[]; -+ /** -+ * Mapping from interactive variables (e.g. ${action.pickProcess}) in `launch.json` to a command. -+ */ -+ readonly variables?: {}; -+ /** -+ * Configurations for generating the initial 'launch.json'. -+ */ -+ readonly initialConfigurations?: unknown[] | string; -+ /** -+ * List of languages for which the debug extension could be considered the "default debugger". -+ */ -+ readonly languages?: unknown[]; -+ /** -+ * Snippets for adding new configurations in 'launch.json'. -+ */ -+ readonly configurationSnippets?: unknown[]; -+ /** -+ * JSON schema configurations for validating 'launch.json'. -+ */ -+ readonly configurationAttributes?: {}; -+ /** -+ * Condition which must be true to enable this type of debugger. Consider using 'shellExecutionSupported', 'virtualWorkspace', 'resourceScheme' or an extension-defined context key as appropriate for this. -+ */ -+ readonly when?: string; -+ /** -+ * When this condition is true, this debugger type is hidden from the debugger list, but is still enabled. -+ */ -+ readonly hiddenWhen?: string; -+ /** -+ * Optional message to mark this debug type as being deprecated. -+ */ -+ readonly deprecated?: string; -+ /** -+ * Windows specific settings. -+ */ -+ readonly windows?: { -+ /** -+ * Runtime used for Windows. -+ */ -+ runtime?: string; -+ }; -+ /** -+ * macOS specific settings. -+ */ -+ readonly osx?: { -+ /** -+ * Runtime used for macOS. -+ */ -+ runtime?: string; -+ }; -+ /** -+ * Linux specific settings. -+ */ -+ readonly linux?: { -+ /** -+ * Runtime used for Linux. -+ */ -+ readonly runtime?: string; -+ }; -+ /** -+ * UI strings contributed by this debug adapter. -+ */ -+ readonly strings?: { -+ /** -+ * When there are unverified breakpoints in a language supported by this debug adapter, this message will appear on the breakpoint hover and in the breakpoints view. Markdown and command links are supported. -+ */ -+ readonly unverifiedBreakpoints?: string; -+ }; - } - - export interface IGrammar { -- language: string; -+ /** -+ * Language identifier for which this syntax is contributed to. -+ */ -+ readonly language: string; -+ /** -+ * Textmate scope name used by the tmLanguage file. -+ */ -+ readonly scopeName: string; -+ /** -+ * Path of the tmLanguage file. The path is relative to the extension folder and typically starts with './syntaxes/'. -+ */ -+ readonly path: string; -+ /** -+ * A map of scope name to language id if this grammar contains embedded languages. -+ */ -+ readonly embeddedLanguages?: {}; -+ /** -+ * A map of scope name to token types. -+ */ -+ readonly tokenTypes?: { -+ [k: string]: 'string' | 'comment' | 'other'; -+ }; -+ /** -+ * List of language scope names to which this grammar is injected to. -+ */ -+ readonly injectTo?: string[]; -+ /** -+ * Defines which scope names contain balanced brackets. -+ */ -+ readonly balancedBracketScopes?: string[]; -+ /** -+ * Defines which scope names do not contain balanced brackets. -+ */ -+ readonly unbalancedBracketScopes?: string[]; - } - - export interface IJSONValidation { -- fileMatch: string | string[]; -- url: string; -+ /** -+ * The file pattern (or an array of patterns) to match, for example "package.json" or "*.launch". Exclusion patterns start with '!' -+ */ -+ readonly fileMatch?: string | string[]; -+ /** -+ * A schema URL ('http:', 'https:') or relative path to the extension folder ('./'). -+ */ -+ readonly url: string; - } - - export interface IKeyBinding { -- command: string; -- key: string; -- when?: string; -- mac?: string; -- linux?: string; -- win?: string; -+ /** -+ * Identifier of the command to run when keybinding is triggered. -+ */ -+ readonly command: string; -+ /** -+ * Arguments to pass to the command to execute. -+ */ -+ readonly args?: { -+ [k: string]: unknown; -+ }; -+ /** -+ * Key or key sequence (separate keys with plus-sign and sequences with space, e.g. Ctrl+O and Ctrl+L L for a chord). -+ */ -+ readonly key: string; -+ /** -+ * Mac specific key or key sequence. -+ */ -+ readonly mac?: string; -+ /** -+ * Linux specific key or key sequence. -+ */ -+ readonly linux?: string; -+ /** -+ * Windows specific key or key sequence. -+ */ -+ readonly win?: string; -+ /** -+ * Condition when the key is active. -+ */ -+ readonly when?: string; - } - - export interface ILanguage { -- id: string; -- extensions: string[]; -- aliases: string[]; -+ /** -+ * ID of the language. -+ */ -+ readonly id: string; -+ /** -+ * Name aliases for the language. -+ */ -+ readonly aliases?: string[]; -+ /** -+ * File extensions associated to the language. -+ */ -+ readonly extensions?: string[]; -+ /** -+ * File names associated to the language. -+ */ -+ readonly filenames?: string[]; -+ /** -+ * File name glob patterns associated to the language. -+ */ -+ readonly filenamePatterns?: string[]; -+ /** -+ * Mime types associated to the language. -+ */ -+ readonly mimetypes?: string[]; -+ /** -+ * A regular expression matching the first line of a file of the language. -+ */ -+ readonly firstLine?: string; -+ /** -+ * A relative path to a file containing configuration options for the language. -+ */ -+ readonly configuration?: string; -+ /** -+ * A icon to use as file icon, if no icon theme provides one for the language. -+ */ -+ readonly icon?: { -+ /** -+ * Icon path when a light theme is used -+ */ -+ readonly light?: string; -+ /** -+ * Icon path when a dark theme is used -+ */ -+ readonly dark?: string; -+ }; - } - - export interface IMenu { -- command: string; -- alt?: string; -- when?: string; -- group?: string; -+ /** -+ * Identifier of the command to execute. The command must be declared in the 'commands'-section -+ */ -+ readonly command: string; -+ /** -+ * Identifier of an alternative command to execute. The command must be declared in the 'commands'-section -+ */ -+ readonly alt?: string; -+ /** -+ * Condition which must be true to show this item -+ */ -+ readonly when?: string; -+ /** -+ * Group into which this item belongs -+ */ -+ readonly group?: string; -+} -+ -+export interface ISubMenu { -+ /** -+ * Identifier of the submenu to display in this item. -+ */ -+ readonly submenu: string; -+ /** -+ * Condition which must be true to show this item -+ */ -+ readonly when?: string; -+ /** -+ * Group into which this item belongs -+ */ -+ readonly group?: string; - } - - export interface ISnippet { -- language: string; -+ /** -+ * Language identifier for which this snippet is contributed to. -+ */ -+ readonly language: string; -+ /** -+ * Path of the snippets file. The path is relative to the extension folder and typically starts with './snippets/'. -+ */ -+ readonly path: string; -+} -+ -+export interface IColorTheme { -+ /** -+ * Id of the color theme as used in the user settings. -+ */ -+ readonly id: string; -+ /** -+ * Label of the color theme as shown in the UI. -+ */ -+ readonly label: string; -+ /** -+ * Base theme defining the colors around the editor: 'vs' is the light color theme, 'vs-dark' is the dark color theme. 'hc-black' is the dark high contrast theme, 'hc-light' is the light high contrast theme. -+ */ -+ readonly uiTheme: 'vs' | 'vs-dark' | 'hc-black' | 'hc-light'; -+ /** -+ * Path of the tmTheme file. The path is relative to the extension folder and is typically './colorthemes/awesome-color-theme.json'. -+ */ -+ readonly path: string; -+} -+ -+export interface IIconTheme { -+ /** -+ * Id of the file icon theme as used in the user settings. -+ */ -+ readonly id: string; -+ /** -+ * Label of the file icon theme as shown in the UI. -+ */ -+ readonly label: string; -+ /** -+ * Path of the file icon theme definition file. The path is relative to the extension folder and is typically './fileicons/awesome-icon-theme.json'. -+ */ -+ readonly path: string; - } - --export interface ITheme { -- label: string; -+export interface IProductTheme { -+ /** -+ * Id of the product icon theme as used in the user settings. -+ */ -+ readonly id: string; -+ /** -+ * Label of the product icon theme as shown in the UI. -+ */ -+ readonly label: string; -+ /** -+ * Path of the product icon theme definition file. The path is relative to the extension folder and is typically './producticons/awesome-product-icon-theme.json'. -+ */ -+ readonly path: string; - } - - export interface IViewContainer { -- id: string; -- title: string; -+ /** -+ * Unique id used to identify the container in which views can be contributed using 'views' contribution point -+ */ -+ readonly id: string; -+ /** -+ * Human readable string used to render the container -+ */ -+ readonly title: string; -+ /** -+ * Path to the container icon. Icons are 24x24 centered on a 50x40 block and have a fill color of 'rgb(215, 218, 224)' or '#d7dae0'. It is recommended that icons be in SVG, though any image file type is accepted. -+ */ -+ readonly icon: string; - } - - export interface IView { -- id: string; -- name: string; -+ readonly type?: 'tree' | 'webview'; -+ readonly id: string; -+ /** -+ * The human-readable name of the view. Will be shown -+ */ -+ readonly name: string; -+ /** -+ * Condition which must be true to show this view -+ */ -+ readonly when?: string; -+ /** -+ * Path to the view icon. View icons are displayed when the name of the view cannot be shown. It is recommended that icons be in SVG, though any image file type is accepted. -+ */ -+ readonly icon?: string; -+ /** -+ * Human-readable context for when the view is moved out of its original location. By default, the view's container name will be used. -+ */ -+ readonly contextualTitle?: string; -+ /** -+ * Initial state of the view when the extension is first installed. Once the user has changed the view state by collapsing, moving, or hiding the view, the initial state will not be used again. -+ */ -+ readonly visibility?: 'visible' | 'hidden' | 'collapsed'; -+ /** -+ * The initial size of the view. The size will behave like the css 'flex' property, and will set the initial size when the view is first shown. In the side bar, this is the height of the view. This value is only respected when the same extension owns both the view and the view container. -+ */ -+ readonly initialSize?: number; - } - - export interface IColor { -- id: string; -- description: string; -- defaults: { light: string; dark: string; highContrast: string }; -+ /** -+ * The identifier of the themable color -+ */ -+ readonly id: string; -+ /** -+ * The description of the themable color -+ */ -+ readonly description: string; -+ readonly defaults: { -+ /** -+ * The default color for light themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. -+ */ -+ readonly light: string; -+ /** -+ * The default color for dark themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. -+ */ -+ readonly dark: string; -+ /** -+ * The default color for high contrast dark themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. If not provided, the `dark` color is used as default for high contrast dark themes. -+ */ -+ readonly highContrast?: string; -+ /** -+ * The default color for high contrast light themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. If not provided, the `light` color is used as default for high contrast light themes. -+ */ -+ readonly highContrastLight?: string; -+ }; - } - - interface IWebviewEditor { - readonly viewType: string; - readonly priority: string; -- readonly selector: readonly { -+ /** -+ * Human readable name of the custom editor. This is displayed to users when selecting which editor to use. -+ */ -+ readonly displayName: string; -+ /** -+ * Set of globs that the custom editor is enabled for. -+ */ -+ readonly selector: { -+ /** -+ * Glob that the custom editor is enabled for. -+ */ - readonly filenamePattern?: string; - }[]; - } - - export interface ICodeActionContributionAction { - readonly kind: string; -+ /** -+ * Label for the code action used in the UI. -+ */ - readonly title: string; -+ /** -+ * Description of what the code action does. -+ */ - readonly description?: string; - } - - export interface ICodeActionContribution { -- readonly languages: readonly string[]; -+ /** -+ * Language modes that the code actions are enabled for. -+ */ -+ readonly languages: string[]; - readonly actions: readonly ICodeActionContributionAction[]; - } - - export interface IAuthenticationContribution { -+ /** -+ * The id of the authentication provider. -+ */ - readonly id: string; -+ /** -+ * The human readable name of the authentication provider. -+ */ - readonly label: string; - } - --export interface IWalkthroughStep { -+export interface IWalkthroughStep2 { - readonly id: string; - readonly title: string; - readonly description: string | undefined; -@@ -133,14 +520,119 @@ export interface IWalkthroughStep { - readonly when?: string; - } - -+export interface IWalkthroughStep { -+ /** -+ * Unique identifier for this step. This is used to keep track of which steps have been completed. -+ */ -+ readonly id: string; -+ /** -+ * Title of step. -+ */ -+ readonly title: string; -+ /** -+ * Description of step. Supports ``preformatted``, __italic__, and **bold** text. Use markdown-style links for commands or external links: [Title](command:myext.command), [Title](command:toSide:myext.command), or [Title](https://aka.ms). Links on their own line will be rendered as buttons. -+ */ -+ readonly description?: string; -+ readonly button?: { -+ [k: string]: unknown; -+ }; -+ /** -+ * Media to show alongside this step, either an image or markdown content. -+ */ -+ readonly media: { -+ readonly path?: { -+ [k: string]: unknown; -+ }; -+ /** -+ * Path to an image - or object consisting of paths to light, dark, and hc images - relative to extension directory. Depending on context, the image will be displayed from 400px to 800px wide, with similar bounds on height. To support HIDPI displays, the image will be rendered at 1.5x scaling, for example a 900 physical pixels wide image will be displayed as 600 logical pixels wide. -+ */ -+ readonly image: string | { -+ /** -+ * Path to the image for dark themes, relative to extension directory. -+ */ -+ readonly dark: string; -+ /** -+ * Path to the image for light themes, relative to extension directory. -+ */ -+ readonly light: string; -+ /** -+ * Path to the image for hc themes, relative to extension directory. -+ */ -+ readonly hc: string; -+ /** -+ * Path to the image for hc light themes, relative to extension directory. -+ */ -+ readonly hcLight: string; -+ }; -+ /** -+ * Alternate text to display when the image cannot be loaded or in screen readers. -+ */ -+ readonly altText: string; -+ readonly markdown?: never; -+ readonly svg?: never; -+ } | { -+ /** -+ * Path to an svg, color tokens are supported in variables to support theming to match the workbench. -+ */ -+ readonly svg: string; -+ /** -+ * Alternate text to display when the image cannot be loaded or in screen readers. -+ */ -+ readonly altText: string; -+ readonly image?: never; -+ readonly markdown?: never; -+ } | { -+ readonly path?: { -+ [k: string]: unknown; -+ }; -+ /** -+ * Path to the markdown document, relative to extension directory. -+ */ -+ readonly markdown: string; -+ readonly image?: never; -+ readonly svg?: never; -+ }; -+ /** -+ * Events that should trigger this step to become checked off. If empty or not defined, the step will check off when any of the step's buttons or links are clicked; if the step has no buttons or links it will check on when it is selected. -+ */ -+ readonly completionEvents?: string[]; -+ /** -+ * Signal to mark step as complete. -+ * @deprecated use `completionEvents: 'onCommand:...'` -+ **/ -+ readonly doneOn?: { command: string }; -+ /** -+ * Context key expression to control the visibility of this step. -+ */ -+ readonly when?: string; -+} -+ - export interface IWalkthrough { -+ /** -+ * Unique identifier for this walkthrough. -+ */ - readonly id: string; -+ /** -+ * Title of walkthrough. -+ */ - readonly title: string; -+ /** -+ * Relative path to the icon of the walkthrough. The path is relative to the extension location. If not specified, the icon defaults to the extension icon if available. -+ */ - readonly icon?: string; -+ /** -+ * Description of walkthrough. -+ */ - readonly description: string; -- readonly steps: IWalkthroughStep[]; -- readonly featuredFor: string[] | undefined; -+ /** -+ * Walkthroughs that match one of these glob patterns appear as 'featured' in workspaces with the specified files. For example, a walkthrough for TypeScript projects might specify `tsconfig.json` here. -+ */ -+ readonly featuredFor?: string[]; -+ /** -+ * Context key expression to control the visibility of this walkthrough. -+ */ - readonly when?: string; -+ readonly steps: IWalkthroughStep[]; - } - - export interface IStartEntry { -@@ -152,14 +644,53 @@ export interface IStartEntry { - } - - export interface INotebookEntry { -+ /** -+ * Type of the notebook. -+ */ - readonly type: string; -+ /** -+ * Human readable name of the notebook. -+ */ - readonly displayName: string; -+ /** -+ * Set of globs that the notebook is for. -+ */ -+ readonly selector: { -+ /** -+ * Glob that the notebook is enabled for. -+ */ -+ readonly filenamePattern?: string; -+ /** -+ * Glob that the notebook is disabled for. -+ */ -+ readonly excludeFileNamePattern?: string; -+ }[]; -+ readonly priority?: 'default' | 'option'; - } - - export interface INotebookRendererContribution { -+ /** -+ * Unique identifier of the notebook output renderer. -+ */ - readonly id: string; -+ /** -+ * Human readable name of the notebook output renderer. -+ */ - readonly displayName: string; -+ readonly dependencies?: string[]; -+ readonly optionalDependencies?: string[]; -+ /** -+ * Defines how and if the renderer needs to communicate with an extension host, via `createRendererMessaging`. Renderers with stronger messaging requirements may not work in all environments. -+ */ -+ readonly requiresMessaging?: 'always' | 'optional' | 'never'; -+ /** -+ * Set of globs that the notebook is for. -+ */ - readonly mimeTypes: string[]; -+ readonly entrypoint: string | { -+ readonly extends: string; -+ readonly path: string; -+ }; - } - - export interface IDebugVisualizationContribution { -@@ -168,43 +699,560 @@ export interface IDebugVisualizationContribution { - } - - export interface ITranslation { -- id: string; -- path: string; -+ /** -+ * Id of VS Code or Extension for which this translation is contributed to. Id of VS Code is always `vscode` and of extension should be in format `publisherId.extensionName`. -+ */ -+ readonly id: string; -+ /** -+ * A relative path to a file containing translations for the language. -+ */ -+ readonly path: string; - } - - export interface ILocalizationContribution { -- languageId: string; -- languageName?: string; -- localizedLanguageName?: string; -- translations: ITranslation[]; -- minimalTranslations?: { [key: string]: string }; -+ /** -+ * Id of the language into which the display strings are translated. -+ */ -+ readonly languageId: string; -+ /** -+ * Name of the language in English. -+ */ -+ readonly languageName?: string; -+ /** -+ * Name of the language in contributed language. -+ */ -+ readonly localizedLanguageName?: string; -+ /** -+ * -+ */ -+ readonly translations: ITranslation[]; -+} -+ -+export interface ITerminal { -+ readonly profiles?: { -+ readonly id: string; -+ readonly title: string; -+ readonly icon?: (string | { -+ /** -+ * Icon path when a light theme is used -+ */ -+ readonly light?: string; -+ /** -+ * Icon path when a dark theme is used -+ */ -+ readonly dark?: string; -+ [k: string]: unknown; -+ }); -+ }[]; -+} -+ -+export interface IStatusBarItem { -+ readonly id: string; -+ /** -+ * The name of the entry, like 'Python Language Indicator', 'Git Status' etc. Try to keep the length of the name short, yet descriptive enough that users can understand what the status bar item is about. -+ */ -+ readonly name: string; -+ /** -+ * The text to show for the entry. You can embed icons in the text by leveraging the `$()`-syntax, like 'Hello $(globe)!' -+ */ -+ readonly text: string; -+ /** -+ * The tooltip text for the entry. -+ */ -+ readonly tooltip?: string; -+ /** -+ * The command to execute when the status bar entry is clicked. -+ */ -+ readonly command?: string; -+ /** -+ * The alignment of the status bar entry. -+ */ -+ readonly alignment: 'left' | 'right'; -+ /** -+ * The priority of the status bar entry. Higher value means the item should be shown more to the left. -+ */ -+ readonly priority?: number; -+ /** -+ * Defines the role and aria label to be used when the status bar entry is focused. -+ */ -+ readonly accessibilityInformation?: { -+ /** -+ * The role of the status bar entry which defines how a screen reader interacts with it. More about aria roles can be found here https://w3c.github.io/aria/#widget_roles -+ */ -+ readonly role?: string; -+ /** -+ * The aria label of the status bar entry. Defaults to the entry's text. -+ */ -+ readonly label?: string; -+ }; -+} -+ -+export interface IRemoteHelp { -+ /** -+ * The url, or a command that returns the url, to your project's Getting Started page, or a walkthrough ID contributed by your project's extension -+ */ -+ readonly getStarted?: string | { -+ /** -+ * The ID of a Get Started walkthrough to open. -+ */ -+ id: string; -+ }; -+ /** -+ * The url, or a command that returns the url, to your project's documentation page -+ */ -+ readonly documentation?: string; -+ /** -+ * The url, or a command that returns the url, to your project's feedback reporter -+ */ -+ readonly feedback?: string; -+ /** -+ * The url, or a command that returns the url, to your project's issue reporter -+ */ -+ readonly reportIssue?: string; -+ /** -+ * The url, or a command that returns the url, to your project's issues list -+ */ -+ readonly issues?: string; -+} -+ -+export interface ITaskDefinitions { -+ /** -+ * The actual task type. Please note that types starting with a '$' are reserved for internal usage. -+ */ -+ readonly type?: string; -+ readonly required?: string[]; -+ /** -+ * Additional properties of the task type -+ */ -+ readonly properties?: { -+ [k: string]: IJSONSchema; -+ }; -+ readonly when?: string; -+} -+ -+export interface IIcon { -+ /** -+ * The description of the themable icon -+ */ -+ readonly description: string; -+ /** -+ * The default of the icon. Either a reference to an extisting ThemeIcon or an icon in an icon font. -+ */ -+ readonly default: string | { -+ /** -+ * The path of the icon font that defines the icon. -+ */ -+ readonly fontPath: string; -+ /** -+ * The character for the icon in the icon font. -+ */ -+ readonly fontCharacter: string; -+ }; -+} -+ -+export interface IDocumentationRefactoring { -+ /** -+ * Label for the documentation used in the UI. -+ */ -+ readonly title: string; -+ /** -+ * When clause. -+ */ -+ readonly when: string; -+ /** -+ * Command executed. -+ */ -+ readonly command: string; -+} -+ -+export interface IDocumentation { -+ /** -+ * Contributed documentation for refactorings. -+ */ -+ readonly refactoring?: IDocumentationRefactoring[]; -+} -+ -+export interface ISubMenu { -+ /** -+ * Identifier of the menu to display as a submenu. -+ */ -+ readonly id: string; -+ /** -+ * The label of the menu item which leads to this submenu. -+ */ -+ readonly label: string; -+ /** -+ * (Optional) Icon which is used to represent the submenu in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `\$(zap)` -+ */ -+ readonly icon?: -+ | string -+ | { -+ /** -+ * Icon path when a light theme is used -+ */ -+ readonly light?: string; -+ /** -+ * Icon path when a dark theme is used -+ */ -+ readonly dark?: string; -+ }; -+} -+ -+interface IResourceLabelFormatters { -+ /** -+ * URI scheme on which to match the formatter on. For example "file". Simple glob patterns are supported. -+ */ -+ readonly scheme: string; -+ /** -+ * URI authority on which to match the formatter on. Simple glob patterns are supported. -+ */ -+ readonly authority?: string; -+ /** -+ * Rules for formatting uri resource labels. -+ */ -+ readonly formatting: { -+ /** -+ * Label rules to display. For example: myLabel:/${path}. ${path}, ${scheme}, ${authority} and ${authoritySuffix} are supported as variables. -+ */ -+ readonly label?: string; -+ /** -+ * Separator to be used in the uri label display. '/' or '' as an example. -+ */ -+ readonly separator?: string; -+ /** -+ * Controls whether `${path}` substitutions should have starting separator characters stripped. -+ */ -+ readonly stripPathStartingSeparator?: boolean; -+ /** -+ * Controls if the start of the uri label should be tildified when possible. -+ */ -+ readonly tildify?: boolean; -+ /** -+ * Suffix appended to the workspace label. -+ */ -+ readonly workspaceSuffix?: string; -+ }; -+} -+ -+export interface ISemanticTokenTypes { -+ /** -+ * The identifier of the semantic token type -+ */ -+ readonly id?: string; -+ /** -+ * The super type of the semantic token type -+ */ -+ readonly superType?: string; -+ /** -+ * The description of the semantic token type -+ */ -+ readonly description?: string; -+} -+ -+export interface ISemanticTokenModifiers { -+ /** -+ * The identifier of the semantic token modifier -+ */ -+ readonly id?: string; -+ /** -+ * The description of the semantic token modifier -+ */ -+ readonly description?: string; -+} -+ -+export interface ISemanticTokenScopes { -+ /** -+ * Lists the languge for which the defaults are. -+ */ -+ readonly language?: string; -+ /** -+ * Maps a semantic token (described by semantic token selector) to one or more textMate scopes used to represent that token. -+ */ -+ readonly scopes?: { -+ [k: string]: string[]; -+ }; -+} -+ -+export interface IBreakpoint { -+ /** -+ * Allow breakpoints for this language. -+ */ -+ readonly language?: string; -+ /** -+ * Condition which must be true to enable breakpoints in this language. Consider matching this to the debugger when clause as appropriate. -+ */ -+ readonly when?: string; -+} -+ -+export interface ITerminalQuickFix { -+ /** -+ * The ID of the quick fix provider -+ */ -+ readonly id: string; -+ /** -+ * A regular expression or string to test the command line against -+ */ -+ readonly commandLineMatcher: string; -+ readonly outputMatcher: { -+ /** -+ * A regular expression or string to test the command line against -+ */ -+ readonly lineMatcher: string; -+ /** -+ * Where the search should begin in the buffer -+ */ -+ readonly anchor: 'top' | 'bottom'; -+ /** -+ * The number of lines vertically from the anchor in the buffer to start matching against -+ */ -+ readonly offset: number; -+ /** -+ * The number of rows to match against, this should be as small as possible for performance reasons -+ */ -+ readonly length: number; -+ }; -+ /** -+ * The command exit result to match on -+ */ -+ readonly commandExitResult: 'success' | 'error'; -+ /** -+ * The kind of the resulting quick fix. This changes how the quick fix is presented. Defaults to `"fix"`. -+ */ -+ readonly kind?: 'default' | 'explain'; -+} -+ -+export interface IInteractiveSession { -+ /** -+ * Unique identifier for this Interactive Session provider. -+ */ -+ readonly id: string; -+ /** -+ * Display name for this Interactive Session provider. -+ */ -+ readonly label: string; -+ /** -+ * An icon for this Interactive Session provider. -+ */ -+ readonly icon?: string; -+ /** -+ * A condition which must be true to enable this Interactive Session provider. -+ */ -+ readonly when?: string; -+} -+ -+export interface INotebook { -+ /** -+ * Type of the notebook. -+ */ -+ readonly type: string; -+ /** -+ * Human readable name of the notebook. -+ */ -+ readonly displayName: string; -+ /** -+ * Set of globs that the notebook is for. -+ */ -+ readonly selector: { -+ /** -+ * Glob that the notebook is enabled for. -+ */ -+ readonly filenamePattern?: string; -+ /** -+ * Glob that the notebook is disabled for. -+ */ -+ readonly excludeFileNamePattern?: string; -+ }[]; -+ readonly priority?: 'default' | 'option'; -+} -+ -+export interface NotebookPreload { -+ /** -+ * Type of the notebook. -+ */ -+ readonly type: string; -+ /** -+ * Path to file loaded in the webview. -+ */ -+ readonly entrypoint: string; -+ /** -+ * Paths to additional resources that should be allowed in the webview. -+ */ -+ readonly localResourceRoots?: string[]; -+} -+ -+export interface IViewsWelcome { -+ readonly view: string; -+ /** -+ * Welcome content to be displayed. The format of the contents is a subset of Markdown, with support for links only. -+ */ -+ readonly contents: string; -+ /** -+ * Condition when the welcome content should be displayed. -+ */ -+ readonly when?: string; -+ /** -+ * Group to which this welcome content belongs. Proposed API. -+ */ -+ readonly group?: string; -+ /** -+ * Condition when the welcome content buttons and command links should be enabled. -+ */ -+ readonly enablement?: string; - } - - export interface IExtensionContributions { -- commands?: ICommand[]; -- configuration?: IConfiguration | IConfiguration[]; -- debuggers?: IDebugger[]; -- grammars?: IGrammar[]; -- jsonValidation?: IJSONValidation[]; -- keybindings?: IKeyBinding[]; -- languages?: ILanguage[]; -- menus?: { [context: string]: IMenu[] }; -- snippets?: ISnippet[]; -- themes?: ITheme[]; -- iconThemes?: ITheme[]; -- productIconThemes?: ITheme[]; -- viewsContainers?: { [location: string]: IViewContainer[] }; -- views?: { [location: string]: IView[] }; -- colors?: IColor[]; -- localizations?: ILocalizationContribution[]; -+ /** -+ * Contributes terminal functionality. -+ */ -+ readonly terminal?: ITerminal; -+ /** -+ * Contributes commands to the command palette. -+ */ -+ readonly commands?: ICommand[]; -+ /** -+ * Contributes configuration settings. -+ */ -+ readonly configuration?: IConfiguration | IConfiguration[]; -+ /** -+ * Contributes debug adapters. -+ */ -+ readonly debuggers?: IDebugger[]; -+ /** -+ * Contributes breakpoints. -+ */ -+ readonly breakpoints?: IBreakpoint[]; -+ /** -+ * Contributes textmate tokenizers. -+ */ -+ readonly grammars?: IGrammar[]; -+ /** -+ * Contributes json schema configuration. -+ */ -+ readonly jsonValidation?: IJSONValidation[]; -+ /** -+ * Contributes keybindings. -+ */ -+ readonly keybindings?: IKeyBinding[]; -+ /** -+ * Contributes language declarations. -+ */ -+ readonly languages?: ILanguage[]; -+ /** -+ * Contributes menu items to the editor -+ */ -+ readonly menus?: { [context: string]: IMenu[] }; -+ /** -+ * Contributes submenu items to the editor -+ */ -+ readonly submenus?: ISubMenu[]; -+ /** -+ * Contributes snippets. -+ */ -+ readonly snippets?: ISnippet[]; -+ /** -+ * Contributes textmate color themes. -+ */ -+ readonly themes?: IColorTheme[]; -+ /** -+ * Contributes file icon themes. -+ */ -+ readonly iconThemes?: IIconTheme[]; -+ /** -+ * Contributes product icon themes. -+ */ -+ readonly productIconThemes?: IProductTheme[]; -+ /** -+ * Contributes views containers to the editor -+ */ -+ readonly viewsContainers?: { [location: string]: IViewContainer[] }; -+ /** -+ * Contributes views to the editor -+ */ -+ readonly views?: { [location: string]: IView[] }; -+ /** -+ * Contributes extension defined themable colors -+ */ -+ readonly colors?: IColor[]; -+ /** -+ * Contributes localizations to the editor -+ */ -+ readonly localizations?: ILocalizationContribution[]; -+ /** -+ * Contributed custom editors. -+ */ - readonly customEditors?: readonly IWebviewEditor[]; - readonly codeActions?: readonly ICodeActionContribution[]; -- authentication?: IAuthenticationContribution[]; -- walkthroughs?: IWalkthrough[]; -- startEntries?: IStartEntry[]; -+ /** -+ * Contributes authentication -+ */ -+ readonly authentication?: IAuthenticationContribution[]; -+ /** -+ * Contribute walkthroughs to help users getting started with your extension. -+ */ -+ readonly walkthroughs?: IWalkthrough[]; -+ readonly startEntries?: IStartEntry[]; -+ /** -+ * Contributes notebook document provider. -+ */ - readonly notebooks?: INotebookEntry[]; -+ /** -+ * Contributes notebook output renderer provider. -+ */ - readonly notebookRenderer?: INotebookRendererContribution[]; - readonly debugVisualizers?: IDebugVisualizationContribution[]; -+ /** -+ * Contributes notebook preloads. -+ */ -+ readonly notebookPreload?: NotebookPreload[]; -+ /** -+ * Contributes items to the status bar. -+ */ -+ readonly statusBarItems?: IStatusBarItem[]; -+ /** -+ * Contributes help information for Remote -+ */ -+ readonly remoteHelp?: IRemoteHelp; -+ /** -+ * Contributes task kinds -+ */ -+ readonly taskDefinitions?: ITaskDefinitions[]; -+ /** -+ * Contributes extension defined themable icons -+ */ -+ readonly icons?: { [id: string]: IIcon }; -+ /** -+ * Contributed documentation. -+ */ -+ readonly documentation?: IDocumentation; -+ /** -+ * Contributes resource label formatting rules. -+ */ -+ readonly resourceLabelFormatters?: IResourceLabelFormatters[]; -+ readonly configurationDefaults?: { [id: string]: any }; -+ /** -+ * Contributes semantic token types. -+ */ -+ readonly semanticTokenTypes?: ISemanticTokenTypes[]; -+ /** -+ * Contributes semantic token modifiers. -+ */ -+ readonly semanticTokenModifiers?: ISemanticTokenModifiers[]; -+ /** -+ * Contributes semantic token scope maps. -+ */ -+ readonly semanticTokenScopes?: ISemanticTokenScopes[]; -+ /** -+ * Contributes terminal quick fixes. -+ */ -+ readonly terminalQuickFixes?: ITerminalQuickFix[]; -+ /** -+ * Contributes an Interactive Session provider -+ */ -+ readonly interactiveSession?: IInteractiveSession[]; -+ /** -+ * Contributed views welcome content. Welcome content will be rendered in tree based views whenever they have no meaningful content to display, ie. the File Explorer when no folder is open. Such content is useful as in-product documentation to drive users to use certain features before they are available. A good example would be a `Clone Repository` button in the File Explorer welcome view. -+ */ -+ readonly viewsWelcome?: IViewsWelcome[]; - } - - export interface IExtensionCapabilities { -diff --git a/src/vs/platform/files/node/diskFileSystemProvider.ts b/src/vs/platform/files/node/diskFileSystemProvider.ts -index 180aa7e2960..d589be25ed6 100644 ---- a/src/vs/platform/files/node/diskFileSystemProvider.ts -+++ b/src/vs/platform/files/node/diskFileSystemProvider.ts -@@ -4,7 +4,6 @@ - *--------------------------------------------------------------------------------------------*/ - - import * as fs from 'fs'; --import { gracefulify } from 'graceful-fs'; - import { Barrier, retry } from 'vs/base/common/async'; - import { ResourceMap } from 'vs/base/common/map'; - import { VSBuffer } from 'vs/base/common/buffer'; -@@ -24,22 +23,9 @@ import { readFileIntoStream } from 'vs/platform/files/common/io'; - import { AbstractNonRecursiveWatcherClient, AbstractUniversalWatcherClient, ILogMessage } from 'vs/platform/files/common/watcher'; - import { ILogService } from 'vs/platform/log/common/log'; - import { AbstractDiskFileSystemProvider, IDiskFileSystemProviderOptions } from 'vs/platform/files/common/diskFileSystemProvider'; --import { toErrorMessage } from 'vs/base/common/errorMessage'; - import { UniversalWatcherClient } from 'vs/platform/files/node/watcher/watcherClient'; - import { NodeJSWatcherClient } from 'vs/platform/files/node/watcher/nodejs/nodejsClient'; - --/** -- * Enable graceful-fs very early from here to have it enabled -- * in all contexts that leverage the disk file system provider. -- */ --(() => { -- try { -- gracefulify(fs); -- } catch (error) { -- console.error(`Error enabling graceful-fs: ${toErrorMessage(error)}`); -- } --})(); -- - export class DiskFileSystemProvider extends AbstractDiskFileSystemProvider implements - IFileSystemProviderWithFileReadWriteCapability, - IFileSystemProviderWithOpenReadWriteCloseCapability, -diff --git a/src/vs/platform/instantiation/common/instantiationService.ts b/src/vs/platform/instantiation/common/instantiationService.ts -index ef9ae6601ce..6182c4881a6 100644 ---- a/src/vs/platform/instantiation/common/instantiationService.ts -+++ b/src/vs/platform/instantiation/common/instantiationService.ts -@@ -195,8 +195,10 @@ export class InstantiationService implements IInstantiationService { - - if (instanceOrDesc instanceof SyncDescriptor) { - const d = { id: dependency.id, desc: instanceOrDesc, _trace: item._trace.branch(dependency.id, true) }; -+ if (!graph.lookup(d)) { -+ stack.push(d); -+ } - graph.insertEdge(item, d); -- stack.push(d); - } - } - } -diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts -index a1d28301611..2ffbae2fd9c 100644 ---- a/src/vs/platform/native/electron-main/nativeHostMainService.ts -+++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts -@@ -495,7 +495,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain - async isAdmin(): Promise { - let isAdmin: boolean; - if (isWindows) { -- isAdmin = (await import('native-is-elevated'))(); -+ isAdmin = (await import('native-is-elevated')).default(); - } else { - isAdmin = process.getuid?.() === 0; - } -diff --git a/src/vs/platform/telemetry/common/1dsAppender.ts b/src/vs/platform/telemetry/common/1dsAppender.ts -index c54187f89c9..a4729fabe2e 100644 ---- a/src/vs/platform/telemetry/common/1dsAppender.ts -+++ b/src/vs/platform/telemetry/common/1dsAppender.ts -@@ -5,7 +5,6 @@ - - import type { IExtendedConfiguration, IExtendedTelemetryItem, ITelemetryItem, ITelemetryUnloadState } from '@microsoft/1ds-core-js'; - import type { IChannelConfiguration, IXHROverride, PostChannel } from '@microsoft/1ds-post-js'; --import { importAMDNodeModule } from 'vs/amdX'; - import { onUnexpectedError } from 'vs/base/common/errors'; - import { mixin } from 'vs/base/common/objects'; - import { ITelemetryAppender, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils'; -@@ -22,8 +21,8 @@ const endpointUrl = 'https://mobile.events.data.microsoft.com/OneCollector/1.0'; - const endpointHealthUrl = 'https://mobile.events.data.microsoft.com/ping'; - - async function getClient(instrumentationKey: string, addInternalFlag?: boolean, xhrOverride?: IXHROverride): Promise { -- const oneDs = await importAMDNodeModule('@microsoft/1ds-core-js', 'dist/ms.core.js'); -- const postPlugin = await importAMDNodeModule('@microsoft/1ds-post-js', 'dist/ms.post.js'); -+ const oneDs = await import('@microsoft/1ds-core-js'); -+ const postPlugin = await import('@microsoft/1ds-post-js'); - const appInsightsCore = new oneDs.AppInsightsCore(); - const collectorChannelPlugin: PostChannel = new postPlugin.PostChannel(); - // Configure the app insights core to send to collector++ and disable logging of debug info -diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts -index ec8182b3c1d..85de100c7c0 100644 ---- a/src/vs/platform/terminal/node/ptyService.ts -+++ b/src/vs/platform/terminal/node/ptyService.ts -@@ -15,7 +15,8 @@ import { RequestStore } from 'vs/platform/terminal/common/requestStore'; - import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IShellLaunchConfig, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, IFixedTerminalDimensions, IPersistentTerminalProcessLaunchConfig, ICrossVersionSerializedTerminalState, ISerializedTerminalState, ITerminalProcessOptions, IPtyHostLatencyMeasurement } from 'vs/platform/terminal/common/terminal'; - import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; - import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment'; --import { Terminal as XtermTerminal } from '@xterm/headless'; -+// Fix/Hack for xterm being build as umd -+import xtermHeadless from '@xterm/headless'; - import type { ISerializeOptions, SerializeAddon as XtermSerializeAddon } from '@xterm/addon-serialize'; - import type { Unicode11Addon as XtermUnicode11Addon } from '@xterm/addon-unicode11'; - import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto } from 'vs/platform/terminal/common/terminalProcess'; -@@ -976,7 +977,7 @@ class MutationLogger { - } - - class XtermSerializer implements ITerminalSerializer { -- private readonly _xterm: XtermTerminal; -+ private readonly _xterm: xtermHeadless.Terminal; - private readonly _shellIntegrationAddon: ShellIntegrationAddon; - private _unicodeAddon?: XtermUnicode11Addon; - -@@ -990,7 +991,7 @@ class XtermSerializer implements ITerminalSerializer { - private _rawReviveBuffer: string | undefined, - logService: ILogService - ) { -- this._xterm = new XtermTerminal({ -+ this._xterm = new xtermHeadless.Terminal({ - cols, - rows, - scrollback, -diff --git a/src/vs/workbench/api/browser/mainThreadExtensionService.ts b/src/vs/workbench/api/browser/mainThreadExtensionService.ts -index 6732d38f5e6..72abfc8af21 100644 ---- a/src/vs/workbench/api/browser/mainThreadExtensionService.ts -+++ b/src/vs/workbench/api/browser/mainThreadExtensionService.ts -@@ -193,6 +193,13 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha - async $asBrowserUri(uri: UriComponents): Promise { - return FileAccess.uriToBrowserUri(URI.revive(uri)); - } -+ -+ async $getAllStaticBrowserUris(): Promise<[UriComponents, UriComponents][]> { -+ return Array.from(FileAccess.getRegisteredBrowserUris(), uri => [ -+ uri, -+ FileAccess.uriToBrowserUri(uri) -+ ]); -+ } - } - - class ExtensionHostProxy implements IExtensionHostProxy { -diff --git a/src/vs/workbench/api/browser/statusBarExtensionPoint.ts b/src/vs/workbench/api/browser/statusBarExtensionPoint.ts -index 99dd3279fe8..b692381eaa2 100644 ---- a/src/vs/workbench/api/browser/statusBarExtensionPoint.ts -+++ b/src/vs/workbench/api/browser/statusBarExtensionPoint.ts -@@ -57,7 +57,7 @@ export interface IExtensionStatusBarItemService { - } - - --class ExtensionStatusBarItemService implements IExtensionStatusBarItemService { -+export class ExtensionStatusBarItemService implements IExtensionStatusBarItemService { - - declare readonly _serviceBrand: undefined; - -diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts -index 5c18ab8657a..d7f00aaca84 100644 ---- a/src/vs/workbench/api/common/extHost.protocol.ts -+++ b/src/vs/workbench/api/common/extHost.protocol.ts -@@ -1436,6 +1436,7 @@ export interface MainThreadExtensionServiceShape extends IDisposable { - $onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void; - $setPerformanceMarks(marks: performance.PerformanceMark[]): Promise; - $asBrowserUri(uri: UriComponents): Promise; -+ $getAllStaticBrowserUris(): Promise<[UriComponents, UriComponents][]>; - } - - export interface SCMProviderFeatures { -diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts -index 91f910aa4c8..4660b516306 100644 ---- a/src/vs/workbench/api/common/extHostExtensionService.ts -+++ b/src/vs/workbench/api/common/extHostExtensionService.ts -@@ -44,7 +44,7 @@ import { Schemas } from 'vs/base/common/network'; - import { IResolveAuthorityResult } from 'vs/workbench/services/extensions/common/extensionHostProxy'; - import { IExtHostLocalizationService } from 'vs/workbench/api/common/extHostLocalizationService'; - import { StopWatch } from 'vs/base/common/stopwatch'; --import { isCI, setTimeout0 } from 'vs/base/common/platform'; -+import { isWebWorker, isCI, setTimeout0 } from 'vs/base/common/platform'; - import { IExtHostManagedSockets } from 'vs/workbench/api/common/extHostManagedSockets'; - import { Dto } from 'vs/workbench/services/extensions/common/proxyIdentifier'; - -@@ -256,9 +256,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme - this._extHostTerminalService.dispose(); - this._activator.dispose(); - -- errors.setUnexpectedErrorHandler((err) => { -- this._logService.error(err); -- }); -+ if (isWebWorker) { -+ errors.setUnexpectedErrorHandler((err) => { -+ this._logService.error(err); -+ }); -+ } - - // Invalidate all proxies - this._extHostContext.dispose(); -diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts -index 2bd275cbc21..b1c93afd65f 100644 ---- a/src/vs/workbench/api/common/extensionHostMain.ts -+++ b/src/vs/workbench/api/common/extensionHostMain.ts -@@ -12,7 +12,7 @@ import { MainContext, MainThreadConsoleShape } from 'vs/workbench/api/common/ext - import { IExtensionHostInitData } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; - import { RPCProtocol } from 'vs/workbench/services/extensions/common/rpcProtocol'; - import { ExtensionIdentifier, IExtensionDescription, IRelaxedExtensionDescription } from 'vs/platform/extensions/common/extensions'; --import { ILogService } from 'vs/platform/log/common/log'; -+import { ILogService, ILoggerService } from 'vs/platform/log/common/log'; - import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; - import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; - import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; -@@ -23,6 +23,10 @@ import { IURITransformerService, URITransformerService } from 'vs/workbench/api/ - import { IExtHostExtensionService, IHostUtils } from 'vs/workbench/api/common/extHostExtensionService'; - import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry'; - import { Mutable } from 'vs/base/common/types'; -+import { isWebWorker } from 'vs/base/common/platform'; -+import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; -+import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -+import { ExtHostLoggerService } from 'vs/workbench/api/common/extHostLoggerService'; - - export interface IExitFn { - (code?: number): any; -@@ -158,10 +162,14 @@ export class ExtensionHostMain { - services.set(IExtHostRpcService, new ExtHostRpcService(this._rpcProtocol)); - services.set(IURITransformerService, new URITransformerService(uriTransformer)); - services.set(IHostUtils, hostUtils); -+ services.set(ILogService, new SyncDescriptor(ExtHostLogService, [true], true)); -+ services.set(ILoggerService, new SyncDescriptor(ExtHostLoggerService, [], true)); - - const instaService: IInstantiationService = new InstantiationService(services, true); - -- instaService.invokeFunction(ErrorHandler.installEarlyHandler); -+ if (isWebWorker) { -+ instaService.invokeFunction(ErrorHandler.installEarlyHandler); -+ } - - // ugly self - inject - this._logService = instaService.invokeFunction(accessor => accessor.get(ILogService)); -@@ -180,8 +188,10 @@ export class ExtensionHostMain { - this._extensionService = instaService.invokeFunction(accessor => accessor.get(IExtHostExtensionService)); - this._extensionService.initialize(); - -- // install error handler that is extension-aware -- instaService.invokeFunction(ErrorHandler.installFullHandler); -+ if (isWebWorker) { -+ // install error handler that is extension-aware -+ instaService.invokeFunction(ErrorHandler.installFullHandler); -+ } - } - - async asBrowserUri(uri: URI): Promise { -@@ -189,10 +199,19 @@ export class ExtensionHostMain { - return URI.revive(await mainThreadExtensionsProxy.$asBrowserUri(uri)); - } - -+ async getAllStaticBrowserUris(): Promise<[URI, URI][]> { -+ const mainThreadExtensionsProxy = this._rpcProtocol.getProxy(MainContext.MainThreadExtensionService); -+ return (await mainThreadExtensionsProxy.$getAllStaticBrowserUris()).map(([from, to]) => [URI.revive(from), URI.revive(to)]); -+ } -+ - terminate(reason: string): void { - this._extensionService.terminate(reason); - } - -+ getExtHostExtensionService(): IExtHostExtensionService { -+ return this._extensionService; -+ } -+ - private static _transform(initData: IExtensionHostInitData, rpcProtocol: RPCProtocol): IExtensionHostInitData { - initData.extensions.allExtensions.forEach((ext) => { - (>ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation)); -diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts -index 5ac0ddc7ec9..6ea024b237b 100644 ---- a/src/vs/workbench/api/node/extHostExtensionService.ts -+++ b/src/vs/workbench/api/node/extHostExtensionService.ts -@@ -19,6 +19,11 @@ import { realpathSync } from 'vs/base/node/extpath'; - import { ExtHostConsoleForwarder } from 'vs/workbench/api/node/extHostConsoleForwarder'; - import { ExtHostDiskFileSystemProvider } from 'vs/workbench/api/node/extHostDiskFileSystemProvider'; - -+// ESM-uncomment-begin -+// import { createRequire } from 'node:module'; -+// globalThis.require = createRequire(import.meta.url); -+// ESM-uncomment-end -+ - class NodeModuleRequireInterceptor extends RequireInterceptor { - - protected _installInterceptor(): void { -@@ -109,7 +114,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { - if (extensionId) { - performance.mark(`code/extHost/willLoadExtensionCode/${extensionId}`); - } -- r = require.__$__nodeRequire(module.fsPath); -+ r = await require(module.fsPath); - } finally { - if (extensionId) { - performance.mark(`code/extHost/didLoadExtensionCode/${extensionId}`); -diff --git a/src/vs/workbench/api/node/extensionHostProcess.ts b/src/vs/workbench/api/node/extensionHostProcess.ts -index 785db7edd43..0ab601bdbfc 100644 ---- a/src/vs/workbench/api/node/extensionHostProcess.ts -+++ b/src/vs/workbench/api/node/extensionHostProcess.ts -@@ -5,7 +5,7 @@ - - import * as nativeWatchdog from 'native-watchdog'; - import * as net from 'net'; --import * as minimist from 'minimist'; -+import minimist from 'minimist'; - import * as performance from 'vs/base/common/performance'; - import type { MessagePortMain } from 'vs/base/parts/sandbox/node/electronTypes'; - import { isCancellationError, isSigPipeError, onUnexpectedError } from 'vs/base/common/errors'; -@@ -56,24 +56,6 @@ const args = minimist(process.argv.slice(2), { - ] - }) as ParsedExtHostArgs; - --// With Electron 2.x and node.js 8.x the "natives" module --// can cause a native crash (see https://github.com/nodejs/node/issues/19891 and --// https://github.com/electron/electron/issues/10905). To prevent this from --// happening we essentially blocklist this module from getting loaded in any --// extension by patching the node require() function. --(function () { -- const Module = globalThis._VSCODE_NODE_MODULES.module as any; -- const originalLoad = Module._load; -- -- Module._load = function (request: string) { -- if (request === 'natives') { -- throw new Error('Either the extension or an NPM dependency is using the [unsupported "natives" node module](https://go.microsoft.com/fwlink/?linkid=871887).'); -- } -- -- return originalLoad.apply(this, arguments); -- }; --})(); -- - // custom process.exit logic... - const nativeExit: IExitFn = process.exit.bind(process); - const nativeOn = process.on.bind(process); -diff --git a/src/vs/workbench/api/node/proxyResolver.ts b/src/vs/workbench/api/node/proxyResolver.ts -index 519924eec13..07dd94be9a2 100644 ---- a/src/vs/workbench/api/node/proxyResolver.ts -+++ b/src/vs/workbench/api/node/proxyResolver.ts -@@ -78,10 +78,10 @@ export function connectProxyResolver( - - function createPatchedModules(params: ProxyAgentParams, resolveProxy: ReturnType) { - return { -- http: Object.assign(http, createHttpPatch(params, http, resolveProxy)), -- https: Object.assign(https, createHttpPatch(params, https, resolveProxy)), -- net: Object.assign(net, createNetPatch(params, net)), -- tls: Object.assign(tls, createTlsPatch(params, tls)) -+ http: Object.assign({ ...http }, createHttpPatch(params, http, resolveProxy)), -+ https: Object.assign({ ...https }, createHttpPatch(params, https, resolveProxy)), -+ net: Object.assign({ ...net }, createNetPatch(params, net)), -+ tls: Object.assign({ ...tls }, createTlsPatch(params, tls)) - }; - } - -diff --git a/src/vs/workbench/api/worker/extHost.worker.services.ts b/src/vs/workbench/api/worker/extHost.worker.services.ts -index 20ec7e138a6..e284ed6752b 100644 ---- a/src/vs/workbench/api/worker/extHost.worker.services.ts -+++ b/src/vs/workbench/api/worker/extHost.worker.services.ts -@@ -3,11 +3,8 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; - import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; --import { ILogService } from 'vs/platform/log/common/log'; - import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; --import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; - import { ExtensionStoragePaths, IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths'; - import { ExtHostExtensionService } from 'vs/workbench/api/worker/extHostExtensionService'; - -@@ -17,6 +14,5 @@ import { ExtHostExtensionService } from 'vs/workbench/api/worker/extHostExtensio - // ### ### - // ######################################################################### - --registerSingleton(ILogService, new SyncDescriptor(ExtHostLogService, [true], true)); - registerSingleton(IExtHostExtensionService, ExtHostExtensionService, InstantiationType.Eager); - registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths, InstantiationType.Eager); -diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts -index b83a462131d..5555f431ba0 100644 ---- a/src/vs/workbench/api/worker/extHostExtensionService.ts -+++ b/src/vs/workbench/api/worker/extHostExtensionService.ts -@@ -3,7 +3,7 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; -+import { IExtensionApiFactory, createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; - import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHostExtensionActivator'; - import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; - import { URI } from 'vs/base/common/uri'; -@@ -12,6 +12,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' - import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes'; - import { timeout } from 'vs/base/common/async'; - import { ExtHostConsoleForwarder } from 'vs/workbench/api/worker/extHostConsoleForwarder'; -+import { isWebWorker } from 'vs/base/common/platform'; - - class WorkerRequireInterceptor extends RequireInterceptor { - -@@ -37,14 +38,17 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { - readonly extensionRuntime = ExtensionRuntime.Webworker; - - private _fakeModules?: WorkerRequireInterceptor; -+ protected _apiFactory?: IExtensionApiFactory; - - protected async _beforeAlmostReadyToRunExtensions(): Promise { -- // make sure console.log calls make it to the render -- this._instaService.createInstance(ExtHostConsoleForwarder); -+ if (isWebWorker) { -+ // make sure console.log calls make it to the render -+ this._instaService.createInstance(ExtHostConsoleForwarder); -+ } - - // initialize API and register actors -- const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); -- this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, { mine: this._myRegistry, all: this._globalRegistry }); -+ this._apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); -+ this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, this._apiFactory, { mine: this._myRegistry, all: this._globalRegistry }); - await this._fakeModules.install(); - performance.mark('code/extHost/didInitAPI'); - -diff --git a/src/vs/workbench/api/worker/extensionHostWorker.ts b/src/vs/workbench/api/worker/extensionHostWorker.ts -index 86136a080e6..8a2608599ee 100644 ---- a/src/vs/workbench/api/worker/extensionHostWorker.ts -+++ b/src/vs/workbench/api/worker/extensionHostWorker.ts -@@ -15,7 +15,6 @@ import * as performance from 'vs/base/common/performance'; - - import 'vs/workbench/api/common/extHost.common.services'; - import 'vs/workbench/api/worker/extHost.worker.services'; --import { FileAccess } from 'vs/base/common/network'; - import { URI } from 'vs/base/common/uri'; - - //#region --- Define, capture, and override some globals -@@ -35,6 +34,7 @@ declare namespace self { - let importScripts: any; - let fetch: _Fetch; - let XMLHttpRequest: any; -+ let importExt: any; - } - - const nativeClose = self.close.bind(self); -@@ -47,7 +47,7 @@ function shouldTransformUri(uri: string): boolean { - // In principle, we could convert any URI, but we have concerns - // that parsing https URIs might end up decoding escape characters - // and result in an unintended transformation -- return /^(file|vscode-remote):/i.test(uri); -+ return /^(file|extension-file|vscode-remote):/i.test(uri); - } - - const nativeFetch = fetch.bind(self); -@@ -89,66 +89,172 @@ self.addEventListener = () => console.trace(`'addEventListener' has been blocked - (self)['webkitResolveLocalFileSystemSyncURL'] = undefined; - (self)['webkitResolveLocalFileSystemURL'] = undefined; - --if ((self).Worker) { -- -- // make sure new Worker(...) always uses blob: (to maintain current origin) -- const _Worker = (self).Worker; -- Worker = function (stringUrl: string | URL, options?: WorkerOptions) { -- if (/^file:/i.test(stringUrl.toString())) { -- stringUrl = FileAccess.uriToBrowserUri(URI.parse(stringUrl.toString())).toString(true); -- } else if (/^vscode-remote:/i.test(stringUrl.toString())) { -- // Supporting transformation of vscode-remote URIs requires an async call to the main thread, -- // but we cannot do this call from within the embedded Worker, and the only way out would be -- // to use templating instead of a function in the web api (`resourceUriProvider`) -- throw new Error(`Creating workers from remote extensions is currently not supported.`); -- } -+function patchWorker(asBrowserUri: (uri: URI) => Promise, getAllStaticBrowserUris: () => Promise<[URI, URI][]>) { -+ if ((self).Worker) { -+ -+ // make sure new Worker(...) always uses blob: (to maintain current origin) -+ const _Worker = (self).Worker; -+ Worker = function (stringUrl: string | URL, options?: WorkerOptions) { -+ if (/^vscode-remote:/i.test(stringUrl.toString())) { -+ // Supporting transformation of vscode-remote URIs requires an async call to the main thread, -+ // but we cannot do this call from within the embedded Worker, and the only way out would be -+ // to use templating instead of a function in the web api (`resourceUriProvider`) -+ throw new Error(`Creating workers from remote extensions is currently not supported.`); -+ } - -- // IMPORTANT: bootstrapFn is stringified and injected as worker blob-url. Because of that it CANNOT -- // have dependencies on other functions or variables. Only constant values are supported. Due to -- // that logic of FileAccess.asBrowserUri had to be copied, see `asWorkerBrowserUrl` (below). -- const bootstrapFnSource = (function bootstrapFn(workerUrl: string) { -- function asWorkerBrowserUrl(url: string | URL | TrustedScriptURL): any { -- if (typeof url === 'string' || url instanceof URL) { -- return String(url).replace(/^file:\/\//i, 'vscode-file://vscode-app'); -- } -- return url; -+ async function getWorkerUri(workerUri: URI): Promise { -+ const [browserUrl, staticBrowserUrls] = await Promise.all([ -+ asBrowserUri(workerUri).then(uri => uri.toString(true)), -+ getAllStaticBrowserUris().then(bindings => Object.fromEntries(bindings.map(([from, to]) => [from.toString(true), to.toString(true)]))) -+ ]); -+ -+ // IMPORTANT: bootstrapFn is stringified and injected as worker blob-url. Because of that it CANNOT -+ // have dependencies on other functions or variables. Only constant values are supported. Due to -+ // that logic of FileAccess.asBrowserUri had to be copied, see `asWorkerBrowserUrl` (below). -+ const bootstrapFnSource = (function bootstrapFn(workerUrl: string, staticBrowserUrls: Record) { -+ function asWorkerBrowserUrl(url: string | URL | TrustedScriptURL): any { -+ if (typeof url === 'string' || url instanceof URL) { -+ url = String(url).replace(/^file:\/\//i, 'vscode-file://vscode-app'); -+ return staticBrowserUrls[url] ?? url; -+ } -+ return url; -+ } -+ -+ const nativeFetch = fetch.bind(self); -+ self.fetch = function (input, init) { -+ if (input instanceof Request) { -+ // Request object - massage not supported -+ return nativeFetch(input, init); -+ } -+ return nativeFetch(asWorkerBrowserUrl(input), init); -+ }; -+ self.XMLHttpRequest = class extends XMLHttpRequest { -+ private notFound = false; -+ override open(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null): void { -+ const transformedUrl = asWorkerBrowserUrl(url); -+ this.notFound = transformedUrl.startsWith('extension-file:'); -+ return super.open(method, transformedUrl, async ?? true, username, password); -+ } -+ override send(body?: Document | XMLHttpRequestBodyInit | null | undefined): void { -+ if (this.notFound) { -+ return; -+ } -+ super.send(body); -+ } -+ override get status() { -+ return this.notFound ? 404 : super.status; -+ } -+ }; -+ const nativeImportScripts = importScripts.bind(self); -+ self.importScripts = (...urls: string[]) => { -+ nativeImportScripts(...urls.map(asWorkerBrowserUrl)); -+ }; -+ -+ self.importExt = (url: string) => { -+ // prevent bundler from trying to transform dynamic import -+ return new Function('url', 'return import(url)')(asWorkerBrowserUrl(url)); -+ }; -+ -+ nativeImportScripts(workerUrl); -+ }).toString(); -+ -+ const js = `(${bootstrapFnSource}('${browserUrl}', ${JSON.stringify(staticBrowserUrls)}))`; -+ -+ const blob = new Blob([js], { type: 'application/javascript' }); -+ return URL.createObjectURL(blob); - } - -- const nativeFetch = fetch.bind(self); -- self.fetch = function (input, init) { -- if (input instanceof Request) { -- // Request object - massage not supported -- return nativeFetch(input, init); -+ options = options || {}; -+ options.name = `${name} -> ${options.name || path.basename(stringUrl.toString())}`; -+ -+ class ExtensionWorker implements Worker { -+ private workerPromise: Promise; -+ constructor(scriptURL: string | URL, options?: WorkerOptions) { -+ this.workerPromise = getWorkerUri(URI.parse(scriptURL instanceof URL ? scriptURL.toString() : scriptURL)).then(url => { -+ return new _Worker(url, options); -+ }); - } -- return nativeFetch(asWorkerBrowserUrl(input), init); -- }; -- self.XMLHttpRequest = class extends XMLHttpRequest { -- override open(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null): void { -- return super.open(method, asWorkerBrowserUrl(url), async ?? true, username, password); -+ -+ private _onmessage: Worker['onmessage'] = null; -+ set onmessage(cb: Worker['onmessage']) { -+ this._onmessage = cb; -+ this.workerPromise.then(worker => { -+ worker.onmessage = cb; -+ }, console.error); - } -- }; -- const nativeImportScripts = importScripts.bind(self); -- self.importScripts = (...urls: string[]) => { -- nativeImportScripts(...urls.map(asWorkerBrowserUrl)); -- }; -- -- nativeImportScripts(workerUrl); -- }).toString(); -- -- const js = `(${bootstrapFnSource}('${stringUrl}'))`; -- options = options || {}; -- options.name = `${name} -> ${options.name || path.basename(stringUrl.toString())}`; -- const blob = new Blob([js], { type: 'application/javascript' }); -- const blobUrl = URL.createObjectURL(blob); -- return new _Worker(blobUrl, options); -- }; - --} else { -- (self).Worker = class extends NestedWorker { -- constructor(stringOrUrl: string | URL, options?: WorkerOptions) { -- super(nativePostMessage, stringOrUrl, { name: path.basename(stringOrUrl.toString()), ...options }); -- } -- }; -+ get onmessage(): Worker['onmessage'] { -+ return this._onmessage; -+ } -+ -+ private _onmessageerror: Worker['onmessageerror'] = null; -+ set onmessageerror(cb: Worker['onmessageerror']) { -+ this._onmessageerror = cb; -+ this.workerPromise.then(worker => { -+ worker.onmessageerror = cb; -+ }, console.error); -+ } -+ -+ get onmessageerror(): Worker['onmessageerror'] { -+ return this._onmessageerror; -+ } -+ -+ private _onerror: Worker['onerror'] = null; -+ set onerror(cb: Worker['onerror']) { -+ this._onerror = cb; -+ this.workerPromise.then(worker => { -+ worker.onerror = cb; -+ }, console.error); -+ } -+ -+ get onerror(): Worker['onerror'] { -+ return this._onerror; -+ } -+ -+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -+ postMessage(message: unknown, options?: any): void { -+ this.workerPromise.then(worker => { -+ worker.postMessage(message, options); -+ }, console.error); -+ } -+ -+ terminate(): void { -+ this.workerPromise.then(worker => { -+ worker.terminate(); -+ }, console.error); -+ } -+ -+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -+ addEventListener(type: any, listener: any, options?: any): void { -+ this.workerPromise.then(worker => { -+ worker.addEventListener(type, listener, options); -+ }, console.error); -+ } -+ -+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -+ removeEventListener(type: any, listener: any, options?: any): void { -+ this.workerPromise.then(worker => { -+ worker.removeEventListener(type, listener, options); -+ }, console.error); -+ } -+ -+ dispatchEvent(event: Event): boolean { -+ this.workerPromise.then(worker => { -+ worker.dispatchEvent(event); -+ }, console.error); -+ return false; -+ } -+ } -+ return new ExtensionWorker(stringUrl, options); -+ }; -+ -+ } else { -+ (self).Worker = class extends NestedWorker { -+ constructor(stringOrUrl: string | URL, options?: WorkerOptions) { -+ super(nativePostMessage, stringOrUrl, { name: path.basename(stringOrUrl.toString()), ...options }); -+ } -+ }; -+ } - } - - //#endregion --- -@@ -255,6 +361,7 @@ export function create(): { onmessage: (message: any) => void } { - ); - - patchFetching(uri => extHostMain.asBrowserUri(uri)); -+ patchWorker(uri => extHostMain.asBrowserUri(uri), () => extHostMain.getAllStaticBrowserUris()); - - onTerminate = (reason: string) => extHostMain.terminate(reason); - }); -diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts -index a2b6007fb79..4efc11d8888 100644 ---- a/src/vs/workbench/browser/layout.ts -+++ b/src/vs/workbench/browser/layout.ts -@@ -52,7 +52,7 @@ import { CustomTitleBarVisibility } from '../../platform/window/common/window'; - - //#region Layout Implementation - --interface ILayoutRuntimeState { -+export interface ILayoutRuntimeState { - activeContainerId: number; - mainWindowFullscreen: boolean; - readonly maximized: Set; -@@ -66,12 +66,12 @@ interface ILayoutRuntimeState { - }; - } - --interface IEditorToOpen { -+export interface IEditorToOpen { - readonly editor: IUntypedEditorInput; - readonly viewColumn?: number; - } - --interface ILayoutInitializationState { -+export interface ILayoutInitializationState { - readonly views: { - readonly defaults: string[] | undefined; - readonly containerToRestore: { -@@ -105,11 +105,11 @@ enum LayoutClasses { - WINDOW_BORDER = 'border' - } - --interface IPathToOpen extends IPath { -+export interface IPathToOpen extends IPath { - readonly viewColumn?: number; - } - --interface IInitialEditorsState { -+export interface IInitialEditorsState { - readonly filesToOpenOrCreate?: IPathToOpen[]; - readonly filesToDiff?: IPathToOpen[]; - readonly filesToMerge?: IPathToOpen[]; -@@ -1541,7 +1541,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi - - layout(): void { - if (!this.disposed) { -- this._mainContainerDimension = getClientArea(this.parent); -+ this._mainContainerDimension = getClientArea(this.state.runtime.mainWindowFullscreen ? mainWindow.document.body : this.parent); - this.logService.trace(`Layout#layout, height: ${this._mainContainerDimension.height}, width: ${this._mainContainerDimension.width}`); - - position(this.mainContainer, 0, 0, 0, 0, 'relative'); -diff --git a/src/vs/workbench/browser/media/style.css b/src/vs/workbench/browser/media/style.css -index db4862c7427..63c0d15ad5e 100644 ---- a/src/vs/workbench/browser/media/style.css -+++ b/src/vs/workbench/browser/media/style.css -@@ -9,56 +9,38 @@ - - /* Font Families (with CJK support) */ - --.mac { font-family: -apple-system, BlinkMacSystemFont, sans-serif; } --.mac:lang(zh-Hans) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; } --.mac:lang(zh-Hant) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; } --.mac:lang(ja) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; } --.mac:lang(ko) { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; } -- --.windows { font-family: "Segoe WPC", "Segoe UI", sans-serif; } --.windows:lang(zh-Hans) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; } --.windows:lang(zh-Hant) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; } --.windows:lang(ja) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; } --.windows:lang(ko) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; } -+.mac .monaco-workbench-part{ font-family: -apple-system, BlinkMacSystemFont, sans-serif; } -+.mac:lang(zh-Hans) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; } -+.mac:lang(zh-Hant) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; } -+.mac:lang(ja) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; } -+.mac:lang(ko) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; } -+ -+.windows .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", sans-serif; } -+.windows:lang(zh-Hans) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; } -+.windows:lang(zh-Hant) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; } -+.windows:lang(ja) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; } -+.windows:lang(ko) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; } - - /* Linux: add `system-ui` as first font and not `Ubuntu` to allow other distribution pick their standard OS font */ --.linux { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; } --.linux:lang(zh-Hans) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; } --.linux:lang(zh-Hant) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; } --.linux:lang(ja) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; } --.linux:lang(ko) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; } -+.linux .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; } -+.linux:lang(zh-Hans) .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; } -+.linux:lang(zh-Hant) .monaco-workbench-partt { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; } -+.linux:lang(ja) .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; } -+.linux:lang(ko) .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; } - --.mac { --monaco-monospace-font: "SF Mono", Monaco, Menlo, Courier, monospace; } --.windows { --monaco-monospace-font: Consolas, "Courier New", monospace; } --.linux { --monaco-monospace-font: "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace; } -+.mac .monaco-workbench-part { --monaco-monospace-font: "SF Mono", Monaco, Menlo, Courier, monospace; } -+.windows .monaco-workbench-part { --monaco-monospace-font: Consolas, "Courier New", monospace; } -+.linux .monaco-workbench-part { --monaco-monospace-font: "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace; } - - /* Global Styles */ - --body { -- height: 100%; -- width: 100%; -- margin: 0; -- padding: 0; -- overflow: hidden; -- font-size: 11px; -- user-select: none; -- -webkit-user-select: none; --} -- --body.web { -- position: fixed; /* prevent bounce effect */ --} -- --.monaco-workbench { -+.monaco-workbench-part { - font-size: 13px; - line-height: 1.4em; -- position: relative; -- z-index: 1; -- overflow: hidden; - color: var(--vscode-foreground); - } - --.monaco-workbench.web { -+.monaco-workbench.web .monaco-workbench-part, .monaco-workbench-part.web { - touch-action: none; /* Disable browser handling of all panning and zooming gestures. Removes 300ms touch delay. */ - } - -@@ -79,65 +61,65 @@ body.web { - border: 0; - } - --.monaco-workbench label { -+.monaco-workbench-part label { - cursor: pointer; - } - --.monaco-workbench a { -+.monaco-workbench-part a { - text-decoration: none; - } - --.monaco-workbench.hc-black p > a, --.monaco-workbench.hc-light p > a { -+.monaco-workbench.hc-black .monaco-workbench-part p > a, -+.monaco-workbench.hc-light .monaco-workbench-part p > a { - text-decoration: underline !important; - } - --.monaco-workbench a:active { -+.monaco-workbench-part a:active { - color: inherit; - background-color: inherit; - } - --.monaco-workbench a.plain { -+.monaco-workbench-part a.plain { - color: inherit; - text-decoration: none; - } - --.monaco-workbench a.plain:hover, --.monaco-workbench a.plain.hover { -+.monaco-workbench-part a.plain:hover, -+.monaco-workbench-part a.plain.hover { - color: inherit; - text-decoration: none; - } - --.monaco-workbench input { -+.monaco-workbench-part input { - color: inherit; - font-family: inherit; - font-size: 100%; - } - --.monaco-workbench input::placeholder { color: var(--vscode-input-placeholderForeground); } --.monaco-workbench input::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } --.monaco-workbench input::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } -+.monaco-workbench-part input::placeholder { color: var(--vscode-input-placeholderForeground); } -+.monaco-workbench-part input::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } -+.monaco-workbench-part input::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } - --.monaco-workbench textarea::placeholder { color: var(--vscode-input-placeholderForeground); } --.monaco-workbench textarea::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } --.monaco-workbench textarea::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } -+.monaco-workbench-part textarea::placeholder { color: var(--vscode-input-placeholderForeground); } -+.monaco-workbench-part textarea::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } -+.monaco-workbench-part textarea::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } - --.monaco-workbench .pointer { -+.monaco-workbench-part .pointer { - cursor: pointer; - } - --.monaco-workbench.mac.monaco-font-aliasing-antialiased { -+.monaco-workbench.mac.monaco-font-aliasing-antialiased.monaco-workbench-part, .monaco-workbench.mac.monaco-font-aliasing-antialiased .monaco-workbench-part { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } - --.monaco-workbench.mac.monaco-font-aliasing-none { -+.monaco-workbench.mac.monaco-font-aliasing-none.monaco-workbench-part, .monaco-workbench.mac.monaco-font-aliasing-none .monaco-workbench-part { - -webkit-font-smoothing: none; - -moz-osx-font-smoothing: unset; - } - - @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { -- .monaco-workbench.mac.monaco-font-aliasing-auto { -+ .monaco-workbench.mac.monaco-font-aliasing-auto.monaco-workbench-part, .monaco-workbench.mac.monaco-font-aliasing-auto .monaco-workbench-part { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } -@@ -172,7 +154,7 @@ body.web { - - /* Custom Dropdown (select) Arrows */ - --.monaco-workbench select { -+.monaco-workbench-part select { - font-family: inherit; - appearance: none; - -webkit-appearance: none; -@@ -202,16 +184,16 @@ body.web { - - /* Keyboard Focus Indication Styles */ - --.monaco-workbench [tabindex="0"]:focus, --.monaco-workbench [tabindex="-1"]:focus, --.monaco-workbench .synthetic-focus, --.monaco-workbench select:focus, --.monaco-workbench input[type="button"]:focus, --.monaco-workbench input[type="text"]:focus, --.monaco-workbench button:focus, --.monaco-workbench textarea:focus, --.monaco-workbench input[type="search"]:focus, --.monaco-workbench input[type="checkbox"]:focus { -+.monaco-workbench-part [tabindex="0"]:focus, -+.monaco-workbench-part [tabindex="-1"]:focus, -+.monaco-workbench-part .synthetic-focus, -+.monaco-workbench-part select:focus, -+.monaco-workbench-part input[type="button"]:focus, -+.monaco-workbench-part input[type="text"]:focus, -+.monaco-workbench-part button:focus, -+.monaco-workbench-part textarea:focus, -+.monaco-workbench-part input[type="search"]:focus, -+.monaco-workbench-part input[type="checkbox"]:focus { - outline-width: 1px; - outline-style: solid; - outline-offset: -1px; -@@ -224,19 +206,19 @@ body.web { - background: transparent; /* Search input focus fix when in high contrast */ - } - --.monaco-workbench input[type="checkbox"]:focus { -+.monaco-workbench-part input[type="checkbox"]:focus { - outline-offset: 2px; - } - --.monaco-workbench [tabindex="0"]:active, --.monaco-workbench [tabindex="-1"]:active, --.monaco-workbench select:active, --.monaco-workbench input[type="button"]:active, --.monaco-workbench input[type="checkbox"]:active { -+.monaco-workbench-part [tabindex="0"]:active, -+.monaco-workbench-part [tabindex="-1"]:active, -+.monaco-workbench-part select:active, -+.monaco-workbench-part input[type="button"]:active, -+.monaco-workbench-part input[type="checkbox"]:active { - outline: 0 !important; /* fixes some flashing outlines from showing up when clicking */ - } - --.monaco-workbench.mac select:focus { -+.monaco-workbench.mac.monaco-workbench-part select:focus, .monaco-workbench.mac .monaco-workbench-part select:focus { - border-color: transparent; /* outline is a square, but border has a radius, so we avoid this glitch when focused (https://github.com/microsoft/vscode/issues/26045) */ - } - -diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts -index 76d6c0c1ee4..3060baec73a 100644 ---- a/src/vs/workbench/browser/parts/compositeBar.ts -+++ b/src/vs/workbench/browser/parts/compositeBar.ts -@@ -476,7 +476,7 @@ export class CompositeBar extends Widget implements ICompositeBar { - // Compute sizes only if visible. Otherwise the size measurment would be computed wrongly. - const currentItemsLength = compositeSwitcherBar.viewItems.length; - compositeSwitcherBar.push(items.map(composite => composite.activityAction)); -- items.map((composite, index) => this.compositeSizeInBar.set(composite.id, this.options.orientation === ActionsOrientation.VERTICAL -+ items.forEach((composite, index) => this.compositeSizeInBar.set(composite.id, this.options.orientation === ActionsOrientation.VERTICAL - ? compositeSwitcherBar.getHeight(currentItemsLength + index) - : compositeSwitcherBar.getWidth(currentItemsLength + index) - )); -diff --git a/src/vs/workbench/browser/parts/editor/editor.autosave.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.autosave.contribution.ts -new file mode 100644 -index 00000000000..c7416d68719 ---- /dev/null -+++ b/src/vs/workbench/browser/parts/editor/editor.autosave.contribution.ts -@@ -0,0 +1,9 @@ -+/*--------------------------------------------------------------------------------------------- -+ * Copyright (c) Microsoft Corporation. All rights reserved. -+ * Licensed under the MIT License. See License.txt in the project root for license information. -+ *--------------------------------------------------------------------------------------------*/ -+ -+import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave'; -+import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; -+ -+registerWorkbenchContribution2(EditorAutoSave.ID, EditorAutoSave, WorkbenchPhase.BlockRestore); -diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts -index ca21ad13864..cd246dcb75b 100644 ---- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts -+++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts -@@ -60,7 +60,6 @@ import { isMacintosh } from 'vs/base/common/platform'; - import { EditorContributionInstantiation, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; - import { FloatingEditorClickMenu } from 'vs/workbench/browser/codeeditor'; - import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; --import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave'; - import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess'; - import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess, AllEditorsByAppearanceQuickAccess, AllEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess'; - import { FileAccess } from 'vs/base/common/network'; -@@ -71,6 +70,7 @@ import { DynamicEditorConfigurations } from 'vs/workbench/browser/parts/editor/e - import { EditorActionsDefaultAction, EditorActionsTitleBarAction, HideEditorActionsAction, HideEditorTabsAction, ShowMultipleEditorTabsAction, ShowSingleEditorTabAction, ZenHideEditorTabsAction, ZenShowMultipleEditorTabsAction, ZenShowSingleEditorTabAction } from 'vs/workbench/browser/actions/layoutActions'; - import { ICommandAction } from 'vs/platform/action/common/action'; - import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -+import './editor.autosave.contribution'; - - //#region Editor Registrations - -@@ -127,7 +127,6 @@ Registry.as(EditorExtensions.EditorFactory).registerEdit - - //#region Workbench Contributions - --registerWorkbenchContribution2(EditorAutoSave.ID, EditorAutoSave, WorkbenchPhase.BlockRestore); - registerWorkbenchContribution2(EditorStatusContribution.ID, EditorStatusContribution, WorkbenchPhase.BlockRestore); - registerWorkbenchContribution2(UntitledTextEditorWorkingCopyEditorHandler.ID, UntitledTextEditorWorkingCopyEditorHandler, WorkbenchPhase.BlockRestore); - registerWorkbenchContribution2(DynamicEditorConfigurations.ID, DynamicEditorConfigurations, WorkbenchPhase.BlockRestore); -diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts -index 05ad43933f8..398a41fb0aa 100644 ---- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts -+++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts -@@ -36,7 +36,7 @@ import { CommandCenterControl } from 'vs/workbench/browser/parts/titlebar/comman - import { Categories } from 'vs/platform/action/common/actionCommonCategories'; - import { WorkbenchToolBar } from 'vs/platform/actions/browser/toolbar'; - import { ACCOUNTS_ACTIVITY_ID, GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity'; --import { SimpleAccountActivityActionViewItem, SimpleGlobalActivityActionViewItem } from 'vs/workbench/browser/parts/globalCompositeBar'; -+import { SimpleGlobalActivityActionViewItem } from 'vs/workbench/browser/parts/globalCompositeBar'; - import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget'; - import { IEditorGroupsContainer, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; - import { ActionRunner, IAction } from 'vs/base/common/actions'; -@@ -524,9 +524,6 @@ export class BrowserTitlebarPart extends Part implements ITitlebarPart { - if (action.id === GLOBAL_ACTIVITY_ID) { - return this.instantiationService.createInstance(SimpleGlobalActivityActionViewItem, { position: () => HoverPosition.BELOW }, options); - } -- if (action.id === ACCOUNTS_ACTIVITY_ID) { -- return this.instantiationService.createInstance(SimpleAccountActivityActionViewItem, { position: () => HoverPosition.BELOW }, options); -- } - } - - // --- Editor Actions -diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts -index f575fa95242..e0fc917b228 100644 ---- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts -+++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts -@@ -679,7 +679,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { - } - - this.panes.filter(view => view.isVisible() !== visible) -- .map((view) => view.setVisible(visible)); -+ .forEach((view) => view.setVisible(visible)); - } - - isVisible(): boolean { -diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts -index 8a311d4bb0e..bea66a053e5 100644 ---- a/src/vs/workbench/browser/workbench.ts -+++ b/src/vs/workbench/browser/workbench.ts -@@ -11,10 +11,7 @@ import { RunOnceScheduler, timeout } from 'vs/base/common/async'; - import { isFirefox, isSafari, isChrome } from 'vs/base/browser/browser'; - import { mark } from 'vs/base/common/performance'; - import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors'; --import { Registry } from 'vs/platform/registry/common/platform'; - import { isWindows, isLinux, isWeb, isNative, isMacintosh } from 'vs/base/common/platform'; --import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; --import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; - import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; - import { Position, Parts, IWorkbenchLayoutService, positionToString } from 'vs/workbench/services/layout/browser/layoutService'; - import { IStorageService, WillSaveStateReason, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -@@ -35,7 +32,6 @@ import { FontMeasurements } from 'vs/editor/browser/config/fontMeasurements'; - import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; - import { ILogService } from 'vs/platform/log/common/log'; - import { toErrorMessage } from 'vs/base/common/errorMessage'; --import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys'; - import { coalesce } from 'vs/base/common/arrays'; - import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; - import { Layout } from 'vs/workbench/browser/layout'; -@@ -76,7 +72,7 @@ export class Workbench extends Layout { - this.registerErrorHandler(logService); - } - -- private registerErrorHandler(logService: ILogService): void { -+ protected registerErrorHandler(logService: ILogService): void { - - // Listen on unhandled rejection events - this._register(addDisposableListener(mainWindow, 'unhandledrejection', event => { -@@ -161,13 +157,6 @@ export class Workbench extends Layout { - // Layout - this.initLayout(accessor); - -- // Registries -- Registry.as(WorkbenchExtensions.Workbench).start(accessor); -- Registry.as(EditorExtensions.EditorFactory).start(accessor); -- -- // Context Keys -- this._register(instantiationService.createInstance(WorkbenchContextKeysHandler)); -- - // Register Listeners - this.registerListeners(lifecycleService, storageService, configurationService, hostService, dialogService); - -@@ -192,7 +181,7 @@ export class Workbench extends Layout { - } - } - -- private initServices(serviceCollection: ServiceCollection): IInstantiationService { -+ protected initServices(serviceCollection: ServiceCollection): IInstantiationService { - - // Layout Service - serviceCollection.set(IWorkbenchLayoutService, this); -@@ -231,7 +220,7 @@ export class Workbench extends Layout { - return instantiationService; - } - -- private registerListeners(lifecycleService: ILifecycleService, storageService: IStorageService, configurationService: IConfigurationService, hostService: IHostService, dialogService: IDialogService): void { -+ protected registerListeners(lifecycleService: ILifecycleService, storageService: IStorageService, configurationService: IConfigurationService, hostService: IHostService, dialogService: IDialogService): void { - - // Configuration changes - this._register(configurationService.onDidChangeConfiguration(e => this.updateFontAliasing(e, configurationService))); -@@ -320,7 +309,7 @@ export class Workbench extends Layout { - } - } - -- private renderWorkbench(instantiationService: IInstantiationService, notificationService: NotificationService, storageService: IStorageService, configurationService: IConfigurationService): void { -+ protected renderWorkbench(instantiationService: IInstantiationService, notificationService: NotificationService, storageService: IStorageService, configurationService: IConfigurationService): void { - - // ARIA - setARIAContainer(this.mainContainer); -@@ -386,7 +375,7 @@ export class Workbench extends Layout { - return part; - } - -- private createNotificationsHandlers(instantiationService: IInstantiationService, notificationService: NotificationService): void { -+ protected createNotificationsHandlers(instantiationService: IInstantiationService, notificationService: NotificationService): void { - - // Instantiate Notification components - const notificationsCenter = this._register(instantiationService.createInstance(NotificationsCenter, this.mainContainer, notificationService.model)); -@@ -414,7 +403,7 @@ export class Workbench extends Layout { - }); - } - -- private restore(lifecycleService: ILifecycleService): void { -+ protected restore(lifecycleService: ILifecycleService): void { - - // Ask each part to restore - try { -diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts -index 7288219657e..d6af0e2dbc7 100644 ---- a/src/vs/workbench/common/views.ts -+++ b/src/vs/workbench/common/views.ts -@@ -252,7 +252,10 @@ class ViewContainersRegistryImpl extends Disposable implements IViewContainersRe - } - - getDefaultViewContainer(location: ViewContainerLocation): ViewContainer | undefined { -- return this.defaultViewContainers.find(viewContainer => this.getViewContainerLocation(viewContainer) === location); -+ const locationViewContainers = this.defaultViewContainers.filter(viewContainer => this.getViewContainerLocation(viewContainer) === location); -+ -+ locationViewContainers.sort((a, b) => (a.order ?? 0) - (b.order ?? 0)); -+ return locationViewContainers[0]; - } - } - -diff --git a/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts b/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts -index 08449bd2cd7..f82ac191725 100644 ---- a/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts -+++ b/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts -@@ -19,7 +19,7 @@ import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/envir - import { IHostService } from 'vs/workbench/services/host/browser/host'; - import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; - --class BrowserExtensionHostDebugService extends ExtensionHostDebugChannelClient implements IExtensionHostDebugService { -+export class BrowserExtensionHostDebugService extends ExtensionHostDebugChannelClient implements IExtensionHostDebugService { - - private static readonly LAST_EXTENSION_DEVELOPMENT_WORKSPACE_KEY = 'debug.lastExtensionDevelopmentWorkspace'; - -diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts -index 991a3df035c..cb0b0288249 100644 ---- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts -+++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts -@@ -39,7 +39,7 @@ import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/r - import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; - import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; - import { Extensions, IExtensionFeaturesManagementService, IExtensionFeaturesRegistry } from 'vs/workbench/services/extensionManagement/common/extensionFeatures'; --import { DefaultIconPath, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -+import { getDefaultIconPath, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; - import { LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensionRunningLocation'; - import { IExtensionHostProfile, IExtensionService, IExtensionsStatus } from 'vs/workbench/services/extensions/common/extensions'; - -@@ -271,8 +271,8 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { - - data.root.classList.toggle('odd', index % 2 === 1); - -- data.elementDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = element.marketplaceInfo?.iconUrlFallback || DefaultIconPath, { once: true })); -- data.icon.src = element.marketplaceInfo?.iconUrl || DefaultIconPath; -+ data.elementDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = element.marketplaceInfo?.iconUrlFallback || getDefaultIconPath(), { once: true })); -+ data.icon.src = element.marketplaceInfo?.iconUrl || getDefaultIconPath(); - - if (!data.icon.complete) { - data.icon.style.visibility = 'hidden'; -diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts -index fa11076ab65..dbca12bf6aa 100644 ---- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts -+++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts -@@ -17,7 +17,7 @@ import { - InstallExtensionEvent, DidUninstallExtensionEvent, InstallOperation, InstallOptions, WEB_EXTENSION_TAG, InstallExtensionResult, - IExtensionsControlManifest, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions, IDeprecationInfo, isTargetPlatformCompatible, InstallExtensionInfo, EXTENSION_IDENTIFIER_REGEX - } from 'vs/platform/extensionManagement/common/extensionManagement'; --import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, DefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -+import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, getDefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; - import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, groupByExtension, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; - import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; - import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -@@ -205,7 +205,7 @@ export class Extension implements IExtension { - } - } - } -- return DefaultIconPath; -+ return getDefaultIconPath(); - } - - get repository(): string | undefined { -diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.save.ts b/src/vs/workbench/contrib/files/browser/fileCommands.save.ts -new file mode 100644 -index 00000000000..e7540d3d049 ---- /dev/null -+++ b/src/vs/workbench/contrib/files/browser/fileCommands.save.ts -@@ -0,0 +1,198 @@ -+/*--------------------------------------------------------------------------------------------- -+ * Copyright (c) Microsoft Corporation. All rights reserved. -+ * Licensed under the MIT License. See License.txt in the project root for license information. -+ *--------------------------------------------------------------------------------------------*/ -+ -+import { toAction } from 'vs/base/common/actions'; -+import { coalesce } from 'vs/base/common/arrays'; -+import { toErrorMessage } from 'vs/base/common/errorMessage'; -+import { isCancellationError } from 'vs/base/common/errors'; -+import { hash } from 'vs/base/common/hash'; -+import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -+import { isEqual } from 'vs/base/common/resources'; -+import { URI } from 'vs/base/common/uri'; -+import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; -+import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; -+import * as nls from 'vs/nls'; -+import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -+import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -+import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; -+import { IListService } from 'vs/platform/list/browser/listService'; -+import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -+import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; -+import { EditorInputCapabilities, EditorResourceAccessor, EditorsOrder, IEditorCommandsContext, IEditorIdentifier, SaveReason, SideBySideEditor } from 'vs/workbench/common/editor'; -+import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; -+import { getOpenEditorsViewMultiSelection } from 'vs/workbench/contrib/files/browser/files'; -+import { GroupsOrder, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -+import { IEditorService, ISaveEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; -+import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -+import { SAVE_ALL_COMMAND_ID, SAVE_ALL_IN_GROUP_COMMAND_ID, SAVE_FILES_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID } from './fileConstants'; -+ -+async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsOptions): Promise { -+ const listService = accessor.get(IListService); -+ const editorGroupService = accessor.get(IEditorGroupsService); -+ const codeEditorService = accessor.get(ICodeEditorService); -+ const textFileService = accessor.get(ITextFileService); -+ -+ // Retrieve selected or active editor -+ let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService); -+ if (!editors) { -+ const activeGroup = editorGroupService.activeGroup; -+ if (activeGroup.activeEditor) { -+ editors = []; -+ -+ // Special treatment for side by side editors: if the active editor -+ // has 2 sides, we consider both, to support saving both sides. -+ // We only allow this when saving, not for "Save As" and not if any -+ // editor is untitled which would bring up a "Save As" dialog too. -+ // In addition, we require the secondary side to be modified to not -+ // trigger a touch operation unexpectedly. -+ // -+ // See also https://github.com/microsoft/vscode/issues/4180 -+ // See also https://github.com/microsoft/vscode/issues/106330 -+ // See also https://github.com/microsoft/vscode/issues/190210 -+ if ( -+ activeGroup.activeEditor instanceof SideBySideEditorInput && -+ !options?.saveAs && !(activeGroup.activeEditor.primary.hasCapability(EditorInputCapabilities.Untitled) || activeGroup.activeEditor.secondary.hasCapability(EditorInputCapabilities.Untitled)) && -+ activeGroup.activeEditor.secondary.isModified() -+ ) { -+ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.primary }); -+ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.secondary }); -+ } else { -+ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor }); -+ } -+ } -+ } -+ -+ if (!editors || editors.length === 0) { -+ return; // nothing to save -+ } -+ -+ // Save editors -+ await doSaveEditors(accessor, editors, options); -+ -+ // Special treatment for embedded editors: if we detect that focus is -+ // inside an embedded code editor, we save that model as well if we -+ // find it in our text file models. Currently, only textual editors -+ // support embedded editors. -+ const focusedCodeEditor = codeEditorService.getFocusedCodeEditor(); -+ if (focusedCodeEditor instanceof EmbeddedCodeEditorWidget && !focusedCodeEditor.isSimpleWidget) { -+ const resource = focusedCodeEditor.getModel()?.uri; -+ -+ // Check that the resource of the model was not saved already -+ if (resource && !editors.some(({ editor }) => isEqual(EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }), resource))) { -+ const model = textFileService.files.get(resource); -+ if (!model?.isReadonly()) { -+ await textFileService.save(resource, options); -+ } -+ } -+ } -+} -+ -+function saveDirtyEditorsOfGroups(accessor: ServicesAccessor, groups: readonly IEditorGroup[], options?: ISaveEditorsOptions): Promise { -+ const dirtyEditors: IEditorIdentifier[] = []; -+ for (const group of groups) { -+ for (const editor of group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { -+ if (editor.isDirty()) { -+ dirtyEditors.push({ groupId: group.id, editor }); -+ } -+ } -+ } -+ -+ return doSaveEditors(accessor, dirtyEditors, options); -+} -+ -+async function doSaveEditors(accessor: ServicesAccessor, editors: IEditorIdentifier[], options?: ISaveEditorsOptions): Promise { -+ const editorService = accessor.get(IEditorService); -+ const notificationService = accessor.get(INotificationService); -+ const instantiationService = accessor.get(IInstantiationService); -+ -+ try { -+ await editorService.save(editors, options); -+ } catch (error) { -+ if (!isCancellationError(error)) { -+ notificationService.notify({ -+ id: editors.map(({ editor }) => hash(editor.resource?.toString())).join(), // ensure unique notification ID per set of editor -+ severity: Severity.Error, -+ message: nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)), -+ actions: { -+ primary: [ -+ toAction({ id: 'workbench.action.files.saveEditors', label: nls.localize('retry', "Retry"), run: () => instantiationService.invokeFunction(accessor => doSaveEditors(accessor, editors, options)) }), -+ toAction({ id: 'workbench.action.files.revertEditors', label: nls.localize('discard', "Discard"), run: () => editorService.revert(editors) }) -+ ] -+ } -+ }); -+ } -+ } -+} -+ -+KeybindingsRegistry.registerCommandAndKeybindingRule({ -+ when: undefined, -+ weight: KeybindingWeight.WorkbenchContrib, -+ primary: KeyMod.CtrlCmd | KeyCode.KeyS, -+ id: SAVE_FILE_COMMAND_ID, -+ handler: accessor => { -+ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */ }); -+ } -+}); -+ -+KeybindingsRegistry.registerCommandAndKeybindingRule({ -+ when: undefined, -+ weight: KeybindingWeight.WorkbenchContrib, -+ primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS), -+ win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS) }, -+ id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, -+ handler: accessor => { -+ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */, skipSaveParticipants: true }); -+ } -+}); -+ -+KeybindingsRegistry.registerCommandAndKeybindingRule({ -+ id: SAVE_FILE_AS_COMMAND_ID, -+ weight: KeybindingWeight.WorkbenchContrib, -+ when: undefined, -+ primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS, -+ handler: accessor => { -+ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, saveAs: true }); -+ } -+}); -+ -+KeybindingsRegistry.registerCommandAndKeybindingRule({ -+ when: undefined, -+ weight: KeybindingWeight.WorkbenchContrib, -+ primary: undefined, -+ mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyS }, -+ win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS) }, -+ id: SAVE_ALL_COMMAND_ID, -+ handler: accessor => { -+ return saveDirtyEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); -+ } -+}); -+ -+CommandsRegistry.registerCommand({ -+ id: SAVE_ALL_IN_GROUP_COMMAND_ID, -+ handler: (accessor, _: URI | object, editorContext: IEditorCommandsContext) => { -+ const editorGroupService = accessor.get(IEditorGroupsService); -+ -+ const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService), accessor.get(IEditorGroupsService)); -+ -+ let groups: readonly IEditorGroup[] | undefined = undefined; -+ if (!contexts.length) { -+ groups = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); -+ } else { -+ groups = coalesce(contexts.map(context => editorGroupService.getGroup(context.groupId))); -+ } -+ -+ return saveDirtyEditorsOfGroups(accessor, groups, { reason: SaveReason.EXPLICIT }); -+ } -+}); -+ -+CommandsRegistry.registerCommand({ -+ id: SAVE_FILES_COMMAND_ID, -+ handler: async accessor => { -+ const editorService = accessor.get(IEditorService); -+ -+ const res = await editorService.saveAll({ includeUntitled: false, reason: SaveReason.EXPLICIT }); -+ return res.success; -+ } -+}); -diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts -index 6fa04545a0e..7fe3e6ecee1 100644 ---- a/src/vs/workbench/contrib/files/browser/fileCommands.ts -+++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts -@@ -3,56 +3,48 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import * as nls from 'vs/nls'; -+import { toErrorMessage } from 'vs/base/common/errorMessage'; -+import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -+import { IDisposable, dispose } from 'vs/base/common/lifecycle'; -+import { Schemas } from 'vs/base/common/network'; -+import { isWeb, isWindows } from 'vs/base/common/platform'; -+import { basename, joinPath } from 'vs/base/common/resources'; - import { URI } from 'vs/base/common/uri'; --import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, EditorsOrder, EditorInputCapabilities } from 'vs/workbench/common/editor'; --import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; --import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/window/common/window'; --import { IHostService } from 'vs/workbench/services/host/browser/host'; --import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; --import { IWorkspaceContextService, UNTITLED_WORKSPACE_NAME } from 'vs/platform/workspace/common/workspace'; --import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, FilesExplorerFocusCondition, ExplorerFolderContext, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; --import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; -+import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -+import { ITextModelService } from 'vs/editor/common/services/resolverService'; -+import * as nls from 'vs/nls'; - import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; --import { toErrorMessage } from 'vs/base/common/errorMessage'; --import { IListService } from 'vs/platform/list/browser/listService'; - import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands'; --import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -+import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -+import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -+import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; -+import { EditorOpenSource, EditorResolution } from 'vs/platform/editor/common/editor'; -+import { IEnvironmentService } from 'vs/platform/environment/common/environment'; - import { IFileService } from 'vs/platform/files/common/files'; --import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; --import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; --import { isWeb, isWindows } from 'vs/base/common/platform'; --import { ITextModelService } from 'vs/editor/common/services/resolverService'; --import { getResourceForCommand, getMultiSelectedResources, getOpenEditorsViewMultiSelection, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; --import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; --import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; --import { Schemas } from 'vs/base/common/network'; --import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; --import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; --import { IEditorService, SIDE_GROUP, ISaveEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; --import { IEditorGroupsService, GroupsOrder, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; -+import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -+import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; - import { ILabelService } from 'vs/platform/label/common/label'; --import { basename, joinPath, isEqual } from 'vs/base/common/resources'; --import { IDisposable, dispose } from 'vs/base/common/lifecycle'; --import { IEnvironmentService } from 'vs/platform/environment/common/environment'; --import { coalesce } from 'vs/base/common/arrays'; --import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; --import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; --import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -+import { IListService } from 'vs/platform/list/browser/listService'; -+import { INotificationService } from 'vs/platform/notification/common/notification'; - import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; --import { isCancellationError } from 'vs/base/common/errors'; --import { toAction } from 'vs/base/common/actions'; --import { EditorOpenSource, EditorResolution } from 'vs/platform/editor/common/editor'; --import { hash } from 'vs/base/common/hash'; --import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; --import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; --import { ViewContainerLocation } from 'vs/workbench/common/views'; --import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; --import { OPEN_TO_SIDE_COMMAND_ID, COMPARE_WITH_SAVED_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, COMPARE_SELECTED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, COPY_PATH_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_WITH_EXPLORER_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_ALL_COMMAND_ID, SAVE_ALL_IN_GROUP_COMMAND_ID, SAVE_FILES_COMMAND_ID, REVERT_FILE_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, PREVIOUS_COMPRESSED_FOLDER, NEXT_COMPRESSED_FOLDER, FIRST_COMPRESSED_FOLDER, LAST_COMPRESSED_FOLDER, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL, NEW_FILE_COMMAND_ID } from './fileConstants'; --import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; -+import { IOpenEmptyWindowOptions, IOpenWindowOptions, IWindowOpenable, isWorkspaceToOpen } from 'vs/platform/window/common/window'; -+import { IWorkspaceContextService, UNTITLED_WORKSPACE_NAME } from 'vs/platform/workspace/common/workspace'; - import { RemoveRootFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; --import { OpenEditorsView } from 'vs/workbench/contrib/files/browser/views/openEditorsView'; -+import { EditorInputCapabilities, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; -+import { ViewContainerLocation } from 'vs/workbench/common/views'; -+import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; -+import { IExplorerService, getMultiSelectedResources, getOpenEditorsViewMultiSelection, getResourceForCommand } from 'vs/workbench/contrib/files/browser/files'; - import { ExplorerView } from 'vs/workbench/contrib/files/browser/views/explorerView'; -+import { OpenEditorsView } from 'vs/workbench/contrib/files/browser/views/openEditorsView'; -+import { ExplorerCompressedFirstFocusContext, ExplorerCompressedFocusContext, ExplorerCompressedLastFocusContext, ExplorerFocusCondition, ExplorerFolderContext, FilesExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; -+import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -+import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; -+import { IHostService } from 'vs/workbench/services/host/browser/host'; -+import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; -+import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; -+import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; -+import { COMPARE_RESOURCE_COMMAND_ID, COMPARE_SELECTED_COMMAND_ID, COMPARE_WITH_SAVED_COMMAND_ID, COPY_PATH_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, FIRST_COMPRESSED_FOLDER, LAST_COMPRESSED_FOLDER, NEW_FILE_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL, NEXT_COMPRESSED_FOLDER, OPEN_TO_SIDE_COMMAND_ID, OPEN_WITH_EXPLORER_COMMAND_ID, PREVIOUS_COMPRESSED_FOLDER, REMOVE_ROOT_FOLDER_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, REVERT_FILE_COMMAND_ID, ResourceSelectedForCompareContext, SELECT_FOR_COMPARE_COMMAND_ID } from './fileConstants'; -+import './fileCommands.save'; - - export const openWindowCommand = (accessor: ServicesAccessor, toOpen: IWindowOpenable[], options?: IOpenWindowOptions) => { - if (Array.isArray(toOpen)) { -@@ -366,175 +358,6 @@ CommandsRegistry.registerCommand({ - - // Save / Save As / Save All / Revert - --async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsOptions): Promise { -- const listService = accessor.get(IListService); -- const editorGroupService = accessor.get(IEditorGroupsService); -- const codeEditorService = accessor.get(ICodeEditorService); -- const textFileService = accessor.get(ITextFileService); -- -- // Retrieve selected or active editor -- let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService); -- if (!editors) { -- const activeGroup = editorGroupService.activeGroup; -- if (activeGroup.activeEditor) { -- editors = []; -- -- // Special treatment for side by side editors: if the active editor -- // has 2 sides, we consider both, to support saving both sides. -- // We only allow this when saving, not for "Save As" and not if any -- // editor is untitled which would bring up a "Save As" dialog too. -- // In addition, we require the secondary side to be modified to not -- // trigger a touch operation unexpectedly. -- // -- // See also https://github.com/microsoft/vscode/issues/4180 -- // See also https://github.com/microsoft/vscode/issues/106330 -- // See also https://github.com/microsoft/vscode/issues/190210 -- if ( -- activeGroup.activeEditor instanceof SideBySideEditorInput && -- !options?.saveAs && !(activeGroup.activeEditor.primary.hasCapability(EditorInputCapabilities.Untitled) || activeGroup.activeEditor.secondary.hasCapability(EditorInputCapabilities.Untitled)) && -- activeGroup.activeEditor.secondary.isModified() -- ) { -- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.primary }); -- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.secondary }); -- } else { -- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor }); -- } -- } -- } -- -- if (!editors || editors.length === 0) { -- return; // nothing to save -- } -- -- // Save editors -- await doSaveEditors(accessor, editors, options); -- -- // Special treatment for embedded editors: if we detect that focus is -- // inside an embedded code editor, we save that model as well if we -- // find it in our text file models. Currently, only textual editors -- // support embedded editors. -- const focusedCodeEditor = codeEditorService.getFocusedCodeEditor(); -- if (focusedCodeEditor instanceof EmbeddedCodeEditorWidget && !focusedCodeEditor.isSimpleWidget) { -- const resource = focusedCodeEditor.getModel()?.uri; -- -- // Check that the resource of the model was not saved already -- if (resource && !editors.some(({ editor }) => isEqual(EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }), resource))) { -- const model = textFileService.files.get(resource); -- if (!model?.isReadonly()) { -- await textFileService.save(resource, options); -- } -- } -- } --} -- --function saveDirtyEditorsOfGroups(accessor: ServicesAccessor, groups: readonly IEditorGroup[], options?: ISaveEditorsOptions): Promise { -- const dirtyEditors: IEditorIdentifier[] = []; -- for (const group of groups) { -- for (const editor of group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { -- if (editor.isDirty()) { -- dirtyEditors.push({ groupId: group.id, editor }); -- } -- } -- } -- -- return doSaveEditors(accessor, dirtyEditors, options); --} -- --async function doSaveEditors(accessor: ServicesAccessor, editors: IEditorIdentifier[], options?: ISaveEditorsOptions): Promise { -- const editorService = accessor.get(IEditorService); -- const notificationService = accessor.get(INotificationService); -- const instantiationService = accessor.get(IInstantiationService); -- -- try { -- await editorService.save(editors, options); -- } catch (error) { -- if (!isCancellationError(error)) { -- notificationService.notify({ -- id: editors.map(({ editor }) => hash(editor.resource?.toString())).join(), // ensure unique notification ID per set of editor -- severity: Severity.Error, -- message: nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)), -- actions: { -- primary: [ -- toAction({ id: 'workbench.action.files.saveEditors', label: nls.localize('retry', "Retry"), run: () => instantiationService.invokeFunction(accessor => doSaveEditors(accessor, editors, options)) }), -- toAction({ id: 'workbench.action.files.revertEditors', label: nls.localize('discard', "Discard"), run: () => editorService.revert(editors) }) -- ] -- } -- }); -- } -- } --} -- --KeybindingsRegistry.registerCommandAndKeybindingRule({ -- when: undefined, -- weight: KeybindingWeight.WorkbenchContrib, -- primary: KeyMod.CtrlCmd | KeyCode.KeyS, -- id: SAVE_FILE_COMMAND_ID, -- handler: accessor => { -- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */ }); -- } --}); -- --KeybindingsRegistry.registerCommandAndKeybindingRule({ -- when: undefined, -- weight: KeybindingWeight.WorkbenchContrib, -- primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS), -- win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS) }, -- id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, -- handler: accessor => { -- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */, skipSaveParticipants: true }); -- } --}); -- --KeybindingsRegistry.registerCommandAndKeybindingRule({ -- id: SAVE_FILE_AS_COMMAND_ID, -- weight: KeybindingWeight.WorkbenchContrib, -- when: undefined, -- primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS, -- handler: accessor => { -- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, saveAs: true }); -- } --}); -- --KeybindingsRegistry.registerCommandAndKeybindingRule({ -- when: undefined, -- weight: KeybindingWeight.WorkbenchContrib, -- primary: undefined, -- mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyS }, -- win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS) }, -- id: SAVE_ALL_COMMAND_ID, -- handler: accessor => { -- return saveDirtyEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); -- } --}); -- --CommandsRegistry.registerCommand({ -- id: SAVE_ALL_IN_GROUP_COMMAND_ID, -- handler: (accessor, _: URI | object, editorContext: IEditorCommandsContext) => { -- const editorGroupService = accessor.get(IEditorGroupsService); -- -- const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService), accessor.get(IEditorGroupsService)); -- -- let groups: readonly IEditorGroup[] | undefined = undefined; -- if (!contexts.length) { -- groups = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); -- } else { -- groups = coalesce(contexts.map(context => editorGroupService.getGroup(context.groupId))); -- } -- -- return saveDirtyEditorsOfGroups(accessor, groups, { reason: SaveReason.EXPLICIT }); -- } --}); -- --CommandsRegistry.registerCommand({ -- id: SAVE_FILES_COMMAND_ID, -- handler: async accessor => { -- const editorService = accessor.get(IEditorService); -- -- const res = await editorService.saveAll({ includeUntitled: false, reason: SaveReason.EXPLICIT }); -- return res.success; -- } --}); -- - CommandsRegistry.registerCommand({ - id: REVERT_FILE_COMMAND_ID, - handler: async accessor => { -diff --git a/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts b/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts -new file mode 100644 -index 00000000000..39509160248 ---- /dev/null -+++ b/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts -@@ -0,0 +1,307 @@ -+/*--------------------------------------------------------------------------------------------- -+ * Copyright (c) Microsoft Corporation. All rights reserved. -+ * Licensed under the MIT License. See License.txt in the project root for license information. -+ *--------------------------------------------------------------------------------------------*/ -+ -+import { isNative, isWeb } from 'vs/base/common/platform'; -+import { editorConfigurationBaseNode } from 'vs/editor/common/config/editorConfigurationSchema'; -+import * as nls from 'vs/nls'; -+import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -+import { AutoSaveConfiguration, FILES_ASSOCIATIONS_CONFIG, FILES_EXCLUDE_CONFIG, FILES_READONLY_EXCLUDE_CONFIG, FILES_READONLY_FROM_PERMISSIONS_CONFIG, FILES_READONLY_INCLUDE_CONFIG, HotExitConfiguration } from 'vs/platform/files/common/files'; -+import { Registry } from 'vs/platform/registry/common/platform'; -+import { SUPPORTED_ENCODINGS } from 'vs/workbench/services/textfile/common/encoding'; -+ -+// Configuration -+const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); -+ -+const hotExitConfiguration: IConfigurationPropertySchema = isNative ? -+ { -+ 'type': 'string', -+ 'scope': ConfigurationScope.APPLICATION, -+ 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], -+ 'default': HotExitConfiguration.ON_EXIT, -+ 'markdownEnumDescriptions': [ -+ nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), -+ nls.localize('hotExit.onExit', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu). All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`'), -+ nls.localize('hotExit.onExitAndWindowClose', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu), and also for any window with a folder opened regardless of whether it\'s the last window. All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`') -+ ], -+ 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) -+ } : { -+ 'type': 'string', -+ 'scope': ConfigurationScope.APPLICATION, -+ 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], -+ 'default': HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, -+ 'markdownEnumDescriptions': [ -+ nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), -+ nls.localize('hotExit.onExitAndWindowCloseBrowser', 'Hot exit will be triggered when the browser quits or the window or tab is closed.') -+ ], -+ 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) -+ }; -+ -+configurationRegistry.registerConfiguration({ -+ 'id': 'files', -+ 'order': 9, -+ 'title': nls.localize('filesConfigurationTitle', "Files"), -+ 'type': 'object', -+ 'properties': { -+ [FILES_EXCLUDE_CONFIG]: { -+ 'type': 'object', -+ 'markdownDescription': nls.localize('exclude', "Configure [glob patterns](https://aka.ms/vscode-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. Refer to the `#search.exclude#` setting to define search-specific excludes. Refer to the `#explorer.excludeGitIgnore#` setting for ignoring files based on your `.gitignore`."), -+ 'default': { -+ ...{ '**/.git': true, '**/.svn': true, '**/.hg': true, '**/CVS': true, '**/.DS_Store': true, '**/Thumbs.db': true }, -+ ...(isWeb ? { '**/*.crswap': true /* filter out swap files used for local file access */ } : undefined) -+ }, -+ 'scope': ConfigurationScope.RESOURCE, -+ 'additionalProperties': { -+ 'anyOf': [ -+ { -+ 'type': 'boolean', -+ 'enum': [true, false], -+ 'enumDescriptions': [nls.localize('trueDescription', "Enable the pattern."), nls.localize('falseDescription', "Disable the pattern.")], -+ 'description': nls.localize('files.exclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), -+ }, -+ { -+ 'type': 'object', -+ 'properties': { -+ 'when': { -+ 'type': 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) -+ 'pattern': '\\w*\\$\\(basename\\)\\w*', -+ 'default': '$(basename).ext', -+ 'markdownDescription': nls.localize({ key: 'files.exclude.when', comment: ['\\$(basename) should not be translated'] }, "Additional check on the siblings of a matching file. Use \\$(basename) as variable for the matching file name.") -+ } -+ } -+ } -+ ] -+ } -+ }, -+ [FILES_ASSOCIATIONS_CONFIG]: { -+ 'type': 'object', -+ 'markdownDescription': nls.localize('associations', "Configure [glob patterns](https://aka.ms/vscode-glob-patterns) of file associations to languages (for example `\"*.extension\": \"html\"`). Patterns will match on the absolute path of a file if they contain a path separator and will match on the name of the file otherwise. These have precedence over the default associations of the languages installed."), -+ 'additionalProperties': { -+ 'type': 'string' -+ } -+ }, -+ 'files.encoding': { -+ 'type': 'string', -+ 'enum': Object.keys(SUPPORTED_ENCODINGS), -+ 'default': 'utf8', -+ 'description': nls.localize('encoding', "The default character set encoding to use when reading and writing files. This setting can also be configured per language."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -+ 'enumDescriptions': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong), -+ 'enumItemLabels': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong) -+ }, -+ 'files.autoGuessEncoding': { -+ 'type': 'boolean', -+ 'default': false, -+ 'markdownDescription': nls.localize('autoGuessEncoding', "When enabled, the editor will attempt to guess the character set encoding when opening files. This setting can also be configured per language. Note, this setting is not respected by text search. Only {0} is respected.", '`#files.encoding#`'), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.eol': { -+ 'type': 'string', -+ 'enum': [ -+ '\n', -+ '\r\n', -+ 'auto' -+ ], -+ 'enumDescriptions': [ -+ nls.localize('eol.LF', "LF"), -+ nls.localize('eol.CRLF', "CRLF"), -+ nls.localize('eol.auto', "Uses operating system specific end of line character.") -+ ], -+ 'default': 'auto', -+ 'description': nls.localize('eol', "The default end of line character."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.enableTrash': { -+ 'type': 'boolean', -+ 'default': true, -+ 'description': nls.localize('useTrash', "Moves files/folders to the OS trash (recycle bin on Windows) when deleting. Disabling this will delete files/folders permanently.") -+ }, -+ 'files.trimTrailingWhitespace': { -+ 'type': 'boolean', -+ 'default': false, -+ 'description': nls.localize('trimTrailingWhitespace', "When enabled, will trim trailing whitespace when saving a file."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.insertFinalNewline': { -+ 'type': 'boolean', -+ 'default': false, -+ 'description': nls.localize('insertFinalNewline', "When enabled, insert a final new line at the end of the file when saving it."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.trimFinalNewlines': { -+ 'type': 'boolean', -+ 'default': false, -+ 'description': nls.localize('trimFinalNewlines', "When enabled, will trim all new lines after the final new line at the end of the file when saving it."), -+ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE, -+ }, -+ 'files.autoSave': { -+ 'type': 'string', -+ 'enum': [AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE], -+ 'markdownEnumDescriptions': [ -+ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.off' }, "An editor with changes is never automatically saved."), -+ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.afterDelay' }, "An editor with changes is automatically saved after the configured `#files.autoSaveDelay#`."), -+ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onFocusChange' }, "An editor with changes is automatically saved when the editor loses focus."), -+ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onWindowChange' }, "An editor with changes is automatically saved when the window loses focus.") -+ ], -+ 'default': isWeb ? AutoSaveConfiguration.AFTER_DELAY : AutoSaveConfiguration.OFF, -+ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSave' }, "Controls [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors that have unsaved changes.", AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE, AutoSaveConfiguration.AFTER_DELAY), -+ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.autoSaveDelay': { -+ 'type': 'number', -+ 'default': 1000, -+ 'minimum': 0, -+ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveDelay' }, "Controls the delay in milliseconds after which an editor with unsaved changes is saved automatically. Only applies when `#files.autoSave#` is set to `{0}`.", AutoSaveConfiguration.AFTER_DELAY), -+ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.autoSaveWorkspaceFilesOnly': { -+ 'type': 'boolean', -+ 'default': false, -+ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWorkspaceFilesOnly' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that are inside the opened workspace. Only applies when `#files.autoSave#` is enabled."), -+ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.autoSaveWhenNoErrors': { -+ 'type': 'boolean', -+ 'default': false, -+ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWhenNoErrors' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that have no errors reported in them at the time the auto save is triggered. Only applies when `#files.autoSave#` is enabled."), -+ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.watcherExclude': { -+ 'type': 'object', -+ 'patternProperties': { -+ '.*': { 'type': 'boolean' } -+ }, -+ 'default': { '**/.git/objects/**': true, '**/.git/subtree-cache/**': true, '**/node_modules/*/**': true, '**/.hg/store/**': true }, -+ 'markdownDescription': nls.localize('watcherExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from file watching. Paths can either be relative to the watched folder or absolute. Glob patterns are matched relative from the watched folder. When you experience the file watcher process consuming a lot of CPU, make sure to exclude large folders that are of less interest (such as build output folders)."), -+ 'scope': ConfigurationScope.RESOURCE -+ }, -+ 'files.watcherInclude': { -+ 'type': 'array', -+ 'items': { -+ 'type': 'string' -+ }, -+ 'default': [], -+ 'description': nls.localize('watcherInclude', "Configure extra paths to watch for changes inside the workspace. By default, all workspace folders will be watched recursively, except for folders that are symbolic links. You can explicitly add absolute or relative paths to support watching folders that are symbolic links. Relative paths will be resolved to an absolute path using the currently opened workspace."), -+ 'scope': ConfigurationScope.RESOURCE -+ }, -+ 'files.hotExit': hotExitConfiguration, -+ 'files.defaultLanguage': { -+ 'type': 'string', -+ 'markdownDescription': nls.localize('defaultLanguage', "The default language identifier that is assigned to new files. If configured to `${activeEditorLanguage}`, will use the language identifier of the currently active text editor if any.") -+ }, -+ [FILES_READONLY_INCLUDE_CONFIG]: { -+ 'type': 'object', -+ 'patternProperties': { -+ '.*': { 'type': 'boolean' } -+ }, -+ 'default': {}, -+ 'markdownDescription': nls.localize('filesReadonlyInclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to mark as read-only. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. You can exclude matching paths via the `#files.readonlyExclude#` setting. Files from readonly file system providers will always be read-only independent of this setting."), -+ 'scope': ConfigurationScope.RESOURCE -+ }, -+ [FILES_READONLY_EXCLUDE_CONFIG]: { -+ 'type': 'object', -+ 'patternProperties': { -+ '.*': { 'type': 'boolean' } -+ }, -+ 'default': {}, -+ 'markdownDescription': nls.localize('filesReadonlyExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from being marked as read-only if they match as a result of the `#files.readonlyInclude#` setting. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. Files from readonly file system providers will always be read-only independent of this setting."), -+ 'scope': ConfigurationScope.RESOURCE -+ }, -+ [FILES_READONLY_FROM_PERMISSIONS_CONFIG]: { -+ 'type': 'boolean', -+ 'markdownDescription': nls.localize('filesReadonlyFromPermissions', "Marks files as read-only when their file permissions indicate as such. This can be overridden via `#files.readonlyInclude#` and `#files.readonlyExclude#` settings."), -+ 'default': false -+ }, -+ 'files.restoreUndoStack': { -+ 'type': 'boolean', -+ 'description': nls.localize('files.restoreUndoStack', "Restore the undo stack when a file is reopened."), -+ 'default': true -+ }, -+ 'files.saveConflictResolution': { -+ 'type': 'string', -+ 'enum': [ -+ 'askUser', -+ 'overwriteFileOnDisk' -+ ], -+ 'enumDescriptions': [ -+ nls.localize('askUser', "Will refuse to save and ask for resolving the save conflict manually."), -+ nls.localize('overwriteFileOnDisk', "Will resolve the save conflict by overwriting the file on disk with the changes in the editor.") -+ ], -+ 'description': nls.localize('files.saveConflictResolution', "A save conflict can occur when a file is saved to disk that was changed by another program in the meantime. To prevent data loss, the user is asked to compare the changes in the editor with the version on disk. This setting should only be changed if you frequently encounter save conflict errors and may result in data loss if used without caution."), -+ 'default': 'askUser', -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -+ }, -+ 'files.dialog.defaultPath': { -+ 'type': 'string', -+ 'pattern': '^((\\/|\\\\\\\\|[a-zA-Z]:\\\\).*)?$', // slash OR UNC-root OR drive-root OR undefined -+ 'patternErrorMessage': nls.localize('defaultPathErrorMessage', "Default path for file dialogs must be an absolute path (e.g. C:\\\\myFolder or /myFolder)."), -+ 'description': nls.localize('fileDialogDefaultPath', "Default path for file dialogs, overriding user's home path. Only used in the absence of a context-specific path, such as most recently opened file or folder."), -+ 'scope': ConfigurationScope.MACHINE -+ }, -+ 'files.simpleDialog.enable': { -+ 'type': 'boolean', -+ 'description': nls.localize('files.simpleDialog.enable', "Enables the simple file dialog for opening and saving files and folders. The simple file dialog replaces the system file dialog when enabled."), -+ 'default': false -+ }, -+ 'files.participants.timeout': { -+ type: 'number', -+ default: 60000, -+ markdownDescription: nls.localize('files.participants.timeout', "Timeout in milliseconds after which file participants for create, rename, and delete are cancelled. Use `0` to disable participants."), -+ } -+ } -+}); -+ -+configurationRegistry.registerConfiguration({ -+ ...editorConfigurationBaseNode, -+ properties: { -+ 'editor.formatOnSave': { -+ 'type': 'boolean', -+ 'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be saved after delay, and the editor must not be shutting down."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -+ }, -+ 'editor.formatOnSaveMode': { -+ 'type': 'string', -+ 'default': 'file', -+ 'enum': [ -+ 'file', -+ 'modifications', -+ 'modificationsIfAvailable' -+ ], -+ 'enumDescriptions': [ -+ nls.localize({ key: 'everything', comment: ['This is the description of an option'] }, "Format the whole file."), -+ nls.localize({ key: 'modification', comment: ['This is the description of an option'] }, "Format modifications (requires source control)."), -+ nls.localize({ key: 'modificationIfAvailable', comment: ['This is the description of an option'] }, "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted."), -+ ], -+ 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is enabled."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -+ }, -+ } -+}); -+ -+configurationRegistry.registerConfiguration({ -+ ...editorConfigurationBaseNode, -+ properties: { -+ 'editor.formatOnSave': { -+ 'type': 'boolean', -+ 'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be saved after delay, and the editor must not be shutting down."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -+ }, -+ 'editor.formatOnSaveMode': { -+ 'type': 'string', -+ 'default': 'file', -+ 'enum': [ -+ 'file', -+ 'modifications', -+ 'modificationsIfAvailable' -+ ], -+ 'enumDescriptions': [ -+ nls.localize({ key: 'everything', comment: ['This is the description of an option'] }, "Format the whole file."), -+ nls.localize({ key: 'modification', comment: ['This is the description of an option'] }, "Format modifications (requires source control)."), -+ nls.localize({ key: 'modificationIfAvailable', comment: ['This is the description of an option'] }, "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted."), -+ ], -+ 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is enabled."), -+ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -+ }, -+ } -+}); -diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts -index 80162ffd007..98d8dec26be 100644 ---- a/src/vs/workbench/contrib/files/browser/files.contribution.ts -+++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts -@@ -3,632 +3,7 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import * as nls from 'vs/nls'; --import { sep } from 'vs/base/common/path'; --import { Registry } from 'vs/platform/registry/common/platform'; --import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; --import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; --import { IFileEditorInput, IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; --import { AutoSaveConfiguration, HotExitConfiguration, FILES_EXCLUDE_CONFIG, FILES_ASSOCIATIONS_CONFIG, FILES_READONLY_INCLUDE_CONFIG, FILES_READONLY_EXCLUDE_CONFIG, FILES_READONLY_FROM_PERMISSIONS_CONFIG } from 'vs/platform/files/common/files'; --import { SortOrder, LexicographicOptions, FILE_EDITOR_INPUT_ID, BINARY_TEXT_FILE_MODE, UndoConfirmLevel, IFilesConfiguration } from 'vs/workbench/contrib/files/common/files'; --import { TextFileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/textFileEditorTracker'; --import { TextFileSaveErrorHandler } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; --import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; --import { BinaryFileEditor } from 'vs/workbench/contrib/files/browser/editors/binaryFileEditor'; --import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; --import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; --import { isNative, isWeb, isWindows } from 'vs/base/common/platform'; --import { ExplorerViewletViewsContribution } from 'vs/workbench/contrib/files/browser/explorerViewlet'; --import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/editor'; --import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; --import { ILabelService } from 'vs/platform/label/common/label'; --import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; --import { ExplorerService, UNDO_REDO_SOURCE } from 'vs/workbench/contrib/files/browser/explorerService'; --import { SUPPORTED_ENCODINGS } from 'vs/workbench/services/textfile/common/encoding'; --import { Schemas } from 'vs/base/common/network'; --import { WorkspaceWatcher } from 'vs/workbench/contrib/files/browser/workspaceWatcher'; --import { editorConfigurationBaseNode } from 'vs/editor/common/config/editorConfigurationSchema'; --import { DirtyFilesIndicator } from 'vs/workbench/contrib/files/common/dirtyFilesIndicator'; --import { UndoCommand, RedoCommand } from 'vs/editor/browser/editorExtensions'; --import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; --import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; --import { FileEditorInputSerializer, FileEditorWorkingCopyEditorHandler } from 'vs/workbench/contrib/files/browser/editors/fileEditorHandler'; --import { ModesRegistry } from 'vs/editor/common/languages/modesRegistry'; --import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; --import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; -- --class FileUriLabelContribution implements IWorkbenchContribution { -- -- static readonly ID = 'workbench.contrib.fileUriLabel'; -- -- constructor(@ILabelService labelService: ILabelService) { -- labelService.registerFormatter({ -- scheme: Schemas.file, -- formatting: { -- label: '${authority}${path}', -- separator: sep, -- tildify: !isWindows, -- normalizeDriveLetter: isWindows, -- authorityPrefix: sep + sep, -- workspaceSuffix: '' -- } -- }); -- } --} -- --registerSingleton(IExplorerService, ExplorerService, InstantiationType.Delayed); -- --// Register file editors -- --Registry.as(EditorExtensions.EditorPane).registerEditorPane( -- EditorPaneDescriptor.create( -- TextFileEditor, -- TextFileEditor.ID, -- nls.localize('textFileEditor', "Text File Editor") -- ), -- [ -- new SyncDescriptor(FileEditorInput) -- ] --); -- --Registry.as(EditorExtensions.EditorPane).registerEditorPane( -- EditorPaneDescriptor.create( -- BinaryFileEditor, -- BinaryFileEditor.ID, -- nls.localize('binaryFileEditor', "Binary File Editor") -- ), -- [ -- new SyncDescriptor(FileEditorInput) -- ] --); -- --// Register default file input factory --Registry.as(EditorExtensions.EditorFactory).registerFileEditorFactory({ -- -- typeId: FILE_EDITOR_INPUT_ID, -- -- createFileEditor: (resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents, instantiationService): IFileEditorInput => { -- return instantiationService.createInstance(FileEditorInput, resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents); -- }, -- -- isFileEditor: (obj): obj is IFileEditorInput => { -- return obj instanceof FileEditorInput; -- } --}); -- --// Register Editor Input Serializer & Handler --Registry.as(EditorExtensions.EditorFactory).registerEditorSerializer(FILE_EDITOR_INPUT_ID, FileEditorInputSerializer); --registerWorkbenchContribution2(FileEditorWorkingCopyEditorHandler.ID, FileEditorWorkingCopyEditorHandler, WorkbenchPhase.BlockRestore); -- --// Register Explorer views --registerWorkbenchContribution2(ExplorerViewletViewsContribution.ID, ExplorerViewletViewsContribution, WorkbenchPhase.BlockStartup); -- --// Register Text File Editor Tracker --registerWorkbenchContribution2(TextFileEditorTracker.ID, TextFileEditorTracker, WorkbenchPhase.BlockStartup); -- --// Register Text File Save Error Handler --registerWorkbenchContribution2(TextFileSaveErrorHandler.ID, TextFileSaveErrorHandler, WorkbenchPhase.BlockStartup); -- --// Register uri display for file uris --registerWorkbenchContribution2(FileUriLabelContribution.ID, FileUriLabelContribution, WorkbenchPhase.BlockStartup); -- --// Register Workspace Watcher --Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored); -- --// Register Dirty Files Indicator --registerWorkbenchContribution2(DirtyFilesIndicator.ID, DirtyFilesIndicator, WorkbenchPhase.BlockStartup); -- --// Configuration --const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); -- --const hotExitConfiguration: IConfigurationPropertySchema = isNative ? -- { -- 'type': 'string', -- 'scope': ConfigurationScope.APPLICATION, -- 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], -- 'default': HotExitConfiguration.ON_EXIT, -- 'markdownEnumDescriptions': [ -- nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), -- nls.localize('hotExit.onExit', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu). All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`'), -- nls.localize('hotExit.onExitAndWindowClose', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu), and also for any window with a folder opened regardless of whether it\'s the last window. All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`') -- ], -- 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) -- } : { -- 'type': 'string', -- 'scope': ConfigurationScope.APPLICATION, -- 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], -- 'default': HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, -- 'markdownEnumDescriptions': [ -- nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), -- nls.localize('hotExit.onExitAndWindowCloseBrowser', 'Hot exit will be triggered when the browser quits or the window or tab is closed.') -- ], -- 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) -- }; -- --configurationRegistry.registerConfiguration({ -- 'id': 'files', -- 'order': 9, -- 'title': nls.localize('filesConfigurationTitle', "Files"), -- 'type': 'object', -- 'properties': { -- [FILES_EXCLUDE_CONFIG]: { -- 'type': 'object', -- 'markdownDescription': nls.localize('exclude', "Configure [glob patterns](https://aka.ms/vscode-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. Refer to the `#search.exclude#` setting to define search-specific excludes. Refer to the `#explorer.excludeGitIgnore#` setting for ignoring files based on your `.gitignore`."), -- 'default': { -- ...{ '**/.git': true, '**/.svn': true, '**/.hg': true, '**/CVS': true, '**/.DS_Store': true, '**/Thumbs.db': true }, -- ...(isWeb ? { '**/*.crswap': true /* filter out swap files used for local file access */ } : undefined) -- }, -- 'scope': ConfigurationScope.RESOURCE, -- 'additionalProperties': { -- 'anyOf': [ -- { -- 'type': 'boolean', -- 'enum': [true, false], -- 'enumDescriptions': [nls.localize('trueDescription', "Enable the pattern."), nls.localize('falseDescription', "Disable the pattern.")], -- 'description': nls.localize('files.exclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), -- }, -- { -- 'type': 'object', -- 'properties': { -- 'when': { -- 'type': 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) -- 'pattern': '\\w*\\$\\(basename\\)\\w*', -- 'default': '$(basename).ext', -- 'markdownDescription': nls.localize({ key: 'files.exclude.when', comment: ['\\$(basename) should not be translated'] }, "Additional check on the siblings of a matching file. Use \\$(basename) as variable for the matching file name.") -- } -- } -- } -- ] -- } -- }, -- [FILES_ASSOCIATIONS_CONFIG]: { -- 'type': 'object', -- 'markdownDescription': nls.localize('associations', "Configure [glob patterns](https://aka.ms/vscode-glob-patterns) of file associations to languages (for example `\"*.extension\": \"html\"`). Patterns will match on the absolute path of a file if they contain a path separator and will match on the name of the file otherwise. These have precedence over the default associations of the languages installed."), -- 'additionalProperties': { -- 'type': 'string' -- } -- }, -- 'files.encoding': { -- 'type': 'string', -- 'enum': Object.keys(SUPPORTED_ENCODINGS), -- 'default': 'utf8', -- 'description': nls.localize('encoding', "The default character set encoding to use when reading and writing files. This setting can also be configured per language."), -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -- 'enumDescriptions': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong), -- 'enumItemLabels': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong) -- }, -- 'files.autoGuessEncoding': { -- 'type': 'boolean', -- 'default': false, -- 'markdownDescription': nls.localize('autoGuessEncoding', "When enabled, the editor will attempt to guess the character set encoding when opening files. This setting can also be configured per language. Note, this setting is not respected by text search. Only {0} is respected.", '`#files.encoding#`'), -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.eol': { -- 'type': 'string', -- 'enum': [ -- '\n', -- '\r\n', -- 'auto' -- ], -- 'enumDescriptions': [ -- nls.localize('eol.LF', "LF"), -- nls.localize('eol.CRLF', "CRLF"), -- nls.localize('eol.auto', "Uses operating system specific end of line character.") -- ], -- 'default': 'auto', -- 'description': nls.localize('eol', "The default end of line character."), -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.enableTrash': { -- 'type': 'boolean', -- 'default': true, -- 'description': nls.localize('useTrash', "Moves files/folders to the OS trash (recycle bin on Windows) when deleting. Disabling this will delete files/folders permanently.") -- }, -- 'files.trimTrailingWhitespace': { -- 'type': 'boolean', -- 'default': false, -- 'description': nls.localize('trimTrailingWhitespace', "When enabled, will trim trailing whitespace when saving a file."), -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.insertFinalNewline': { -- 'type': 'boolean', -- 'default': false, -- 'description': nls.localize('insertFinalNewline', "When enabled, insert a final new line at the end of the file when saving it."), -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.trimFinalNewlines': { -- 'type': 'boolean', -- 'default': false, -- 'description': nls.localize('trimFinalNewlines', "When enabled, will trim all new lines after the final new line at the end of the file when saving it."), -- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE, -- }, -- 'files.autoSave': { -- 'type': 'string', -- 'enum': [AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE], -- 'markdownEnumDescriptions': [ -- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.off' }, "An editor with changes is never automatically saved."), -- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.afterDelay' }, "An editor with changes is automatically saved after the configured `#files.autoSaveDelay#`."), -- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onFocusChange' }, "An editor with changes is automatically saved when the editor loses focus."), -- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onWindowChange' }, "An editor with changes is automatically saved when the window loses focus.") -- ], -- 'default': isWeb ? AutoSaveConfiguration.AFTER_DELAY : AutoSaveConfiguration.OFF, -- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSave' }, "Controls [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors that have unsaved changes.", AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE, AutoSaveConfiguration.AFTER_DELAY), -- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.autoSaveDelay': { -- 'type': 'number', -- 'default': 1000, -- 'minimum': 0, -- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveDelay' }, "Controls the delay in milliseconds after which an editor with unsaved changes is saved automatically. Only applies when `#files.autoSave#` is set to `{0}`.", AutoSaveConfiguration.AFTER_DELAY), -- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.autoSaveWorkspaceFilesOnly': { -- 'type': 'boolean', -- 'default': false, -- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWorkspaceFilesOnly' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that are inside the opened workspace. Only applies when `#files.autoSave#` is enabled."), -- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.autoSaveWhenNoErrors': { -- 'type': 'boolean', -- 'default': false, -- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWhenNoErrors' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that have no errors reported in them at the time the auto save is triggered. Only applies when `#files.autoSave#` is enabled."), -- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.watcherExclude': { -- 'type': 'object', -- 'patternProperties': { -- '.*': { 'type': 'boolean' } -- }, -- 'default': { '**/.git/objects/**': true, '**/.git/subtree-cache/**': true, '**/node_modules/*/**': true, '**/.hg/store/**': true }, -- 'markdownDescription': nls.localize('watcherExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from file watching. Paths can either be relative to the watched folder or absolute. Glob patterns are matched relative from the watched folder. When you experience the file watcher process consuming a lot of CPU, make sure to exclude large folders that are of less interest (such as build output folders)."), -- 'scope': ConfigurationScope.RESOURCE -- }, -- 'files.watcherInclude': { -- 'type': 'array', -- 'items': { -- 'type': 'string' -- }, -- 'default': [], -- 'description': nls.localize('watcherInclude', "Configure extra paths to watch for changes inside the workspace. By default, all workspace folders will be watched recursively, except for folders that are symbolic links. You can explicitly add absolute or relative paths to support watching folders that are symbolic links. Relative paths will be resolved to an absolute path using the currently opened workspace."), -- 'scope': ConfigurationScope.RESOURCE -- }, -- 'files.hotExit': hotExitConfiguration, -- 'files.defaultLanguage': { -- 'type': 'string', -- 'markdownDescription': nls.localize('defaultLanguage', "The default language identifier that is assigned to new files. If configured to `${activeEditorLanguage}`, will use the language identifier of the currently active text editor if any.") -- }, -- [FILES_READONLY_INCLUDE_CONFIG]: { -- 'type': 'object', -- 'patternProperties': { -- '.*': { 'type': 'boolean' } -- }, -- 'default': {}, -- 'markdownDescription': nls.localize('filesReadonlyInclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to mark as read-only. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. You can exclude matching paths via the `#files.readonlyExclude#` setting. Files from readonly file system providers will always be read-only independent of this setting."), -- 'scope': ConfigurationScope.RESOURCE -- }, -- [FILES_READONLY_EXCLUDE_CONFIG]: { -- 'type': 'object', -- 'patternProperties': { -- '.*': { 'type': 'boolean' } -- }, -- 'default': {}, -- 'markdownDescription': nls.localize('filesReadonlyExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from being marked as read-only if they match as a result of the `#files.readonlyInclude#` setting. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. Files from readonly file system providers will always be read-only independent of this setting."), -- 'scope': ConfigurationScope.RESOURCE -- }, -- [FILES_READONLY_FROM_PERMISSIONS_CONFIG]: { -- 'type': 'boolean', -- 'markdownDescription': nls.localize('filesReadonlyFromPermissions', "Marks files as read-only when their file permissions indicate as such. This can be overridden via `#files.readonlyInclude#` and `#files.readonlyExclude#` settings."), -- 'default': false -- }, -- 'files.restoreUndoStack': { -- 'type': 'boolean', -- 'description': nls.localize('files.restoreUndoStack', "Restore the undo stack when a file is reopened."), -- 'default': true -- }, -- 'files.saveConflictResolution': { -- 'type': 'string', -- 'enum': [ -- 'askUser', -- 'overwriteFileOnDisk' -- ], -- 'enumDescriptions': [ -- nls.localize('askUser', "Will refuse to save and ask for resolving the save conflict manually."), -- nls.localize('overwriteFileOnDisk', "Will resolve the save conflict by overwriting the file on disk with the changes in the editor.") -- ], -- 'description': nls.localize('files.saveConflictResolution', "A save conflict can occur when a file is saved to disk that was changed by another program in the meantime. To prevent data loss, the user is asked to compare the changes in the editor with the version on disk. This setting should only be changed if you frequently encounter save conflict errors and may result in data loss if used without caution."), -- 'default': 'askUser', -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE -- }, -- 'files.dialog.defaultPath': { -- 'type': 'string', -- 'pattern': '^((\\/|\\\\\\\\|[a-zA-Z]:\\\\).*)?$', // slash OR UNC-root OR drive-root OR undefined -- 'patternErrorMessage': nls.localize('defaultPathErrorMessage', "Default path for file dialogs must be an absolute path (e.g. C:\\\\myFolder or /myFolder)."), -- 'description': nls.localize('fileDialogDefaultPath', "Default path for file dialogs, overriding user's home path. Only used in the absence of a context-specific path, such as most recently opened file or folder."), -- 'scope': ConfigurationScope.MACHINE -- }, -- 'files.simpleDialog.enable': { -- 'type': 'boolean', -- 'description': nls.localize('files.simpleDialog.enable', "Enables the simple file dialog for opening and saving files and folders. The simple file dialog replaces the system file dialog when enabled."), -- 'default': false -- }, -- 'files.participants.timeout': { -- type: 'number', -- default: 60000, -- markdownDescription: nls.localize('files.participants.timeout', "Timeout in milliseconds after which file participants for create, rename, and delete are cancelled. Use `0` to disable participants."), -- } -- } --}); -- --configurationRegistry.registerConfiguration({ -- ...editorConfigurationBaseNode, -- properties: { -- 'editor.formatOnSave': { -- 'type': 'boolean', -- 'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be saved after delay, and the editor must not be shutting down."), -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -- }, -- 'editor.formatOnSaveMode': { -- 'type': 'string', -- 'default': 'file', -- 'enum': [ -- 'file', -- 'modifications', -- 'modificationsIfAvailable' -- ], -- 'enumDescriptions': [ -- nls.localize({ key: 'everything', comment: ['This is the description of an option'] }, "Format the whole file."), -- nls.localize({ key: 'modification', comment: ['This is the description of an option'] }, "Format modifications (requires source control)."), -- nls.localize({ key: 'modificationIfAvailable', comment: ['This is the description of an option'] }, "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted."), -- ], -- 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is enabled."), -- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, -- }, -- } --}); -- --configurationRegistry.registerConfiguration({ -- 'id': 'explorer', -- 'order': 10, -- 'title': nls.localize('explorerConfigurationTitle', "File Explorer"), -- 'type': 'object', -- 'properties': { -- 'explorer.openEditors.visible': { -- 'type': 'number', -- 'description': nls.localize({ key: 'openEditorsVisible', comment: ['Open is an adjective'] }, "The initial maximum number of editors shown in the Open Editors pane. Exceeding this limit will show a scroll bar and allow resizing the pane to display more items."), -- 'default': 9, -- 'minimum': 1 -- }, -- 'explorer.openEditors.minVisible': { -- 'type': 'number', -- 'description': nls.localize({ key: 'openEditorsVisibleMin', comment: ['Open is an adjective'] }, "The minimum number of editor slots pre-allocated in the Open Editors pane. If set to 0 the Open Editors pane will dynamically resize based on the number of editors."), -- 'default': 0, -- 'minimum': 0 -- }, -- 'explorer.openEditors.sortOrder': { -- 'type': 'string', -- 'enum': ['editorOrder', 'alphabetical', 'fullPath'], -- 'description': nls.localize({ key: 'openEditorsSortOrder', comment: ['Open is an adjective'] }, "Controls the sorting order of editors in the Open Editors pane."), -- 'enumDescriptions': [ -- nls.localize('sortOrder.editorOrder', 'Editors are ordered in the same order editor tabs are shown.'), -- nls.localize('sortOrder.alphabetical', 'Editors are ordered alphabetically by tab name inside each editor group.'), -- nls.localize('sortOrder.fullPath', 'Editors are ordered alphabetically by full path inside each editor group.') -- ], -- 'default': 'editorOrder' -- }, -- 'explorer.autoReveal': { -- 'type': ['boolean', 'string'], -- 'enum': [true, false, 'focusNoScroll'], -- 'default': true, -- 'enumDescriptions': [ -- nls.localize('autoReveal.on', 'Files will be revealed and selected.'), -- nls.localize('autoReveal.off', 'Files will not be revealed and selected.'), -- nls.localize('autoReveal.focusNoScroll', 'Files will not be scrolled into view, but will still be focused.'), -- ], -- 'description': nls.localize('autoReveal', "Controls whether the Explorer should automatically reveal and select files when opening them.") -- }, -- 'explorer.autoRevealExclude': { -- 'type': 'object', -- 'markdownDescription': nls.localize('autoRevealExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) for excluding files and folders from being revealed and selected in the Explorer when they are opened. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths."), -- 'default': { '**/node_modules': true, '**/bower_components': true }, -- 'additionalProperties': { -- 'anyOf': [ -- { -- 'type': 'boolean', -- 'description': nls.localize('explorer.autoRevealExclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), -- }, -- { -- type: 'object', -- properties: { -- when: { -- type: 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) -- pattern: '\\w*\\$\\(basename\\)\\w*', -- default: '$(basename).ext', -- description: nls.localize('explorer.autoRevealExclude.when', 'Additional check on the siblings of a matching file. Use $(basename) as variable for the matching file name.') -- } -- } -- } -- ] -- } -- }, -- 'explorer.enableDragAndDrop': { -- 'type': 'boolean', -- 'description': nls.localize('enableDragAndDrop', "Controls whether the Explorer should allow to move files and folders via drag and drop. This setting only effects drag and drop from inside the Explorer."), -- 'default': true -- }, -- 'explorer.confirmDragAndDrop': { -- 'type': 'boolean', -- 'description': nls.localize('confirmDragAndDrop', "Controls whether the Explorer should ask for confirmation to move files and folders via drag and drop."), -- 'default': true -- }, -- 'explorer.confirmPasteNative': { -- 'type': 'boolean', -- 'description': nls.localize('confirmPasteNative', "Controls whether the Explorer should ask for confirmation when pasting native files and folders."), -- 'default': true -- }, -- 'explorer.confirmDelete': { -- 'type': 'boolean', -- 'description': nls.localize('confirmDelete', "Controls whether the Explorer should ask for confirmation when deleting a file via the trash."), -- 'default': true -- }, -- 'explorer.enableUndo': { -- 'type': 'boolean', -- 'description': nls.localize('enableUndo', "Controls whether the Explorer should support undoing file and folder operations."), -- 'default': true -- }, -- 'explorer.confirmUndo': { -- 'type': 'string', -- 'enum': [UndoConfirmLevel.Verbose, UndoConfirmLevel.Default, UndoConfirmLevel.Light], -- 'description': nls.localize('confirmUndo', "Controls whether the Explorer should ask for confirmation when undoing."), -- 'default': UndoConfirmLevel.Default, -- 'enumDescriptions': [ -- nls.localize('enableUndo.verbose', 'Explorer will prompt before all undo operations.'), -- nls.localize('enableUndo.default', 'Explorer will prompt before destructive undo operations.'), -- nls.localize('enableUndo.light', 'Explorer will not prompt before undo operations when focused.'), -- ], -- }, -- 'explorer.expandSingleFolderWorkspaces': { -- 'type': 'boolean', -- 'description': nls.localize('expandSingleFolderWorkspaces', "Controls whether the Explorer should expand multi-root workspaces containing only one folder during initialization"), -- 'default': true -- }, -- 'explorer.sortOrder': { -- 'type': 'string', -- 'enum': [SortOrder.Default, SortOrder.Mixed, SortOrder.FilesFirst, SortOrder.Type, SortOrder.Modified, SortOrder.FoldersNestsFiles], -- 'default': SortOrder.Default, -- 'enumDescriptions': [ -- nls.localize('sortOrder.default', 'Files and folders are sorted by their names. Folders are displayed before files.'), -- nls.localize('sortOrder.mixed', 'Files and folders are sorted by their names. Files are interwoven with folders.'), -- nls.localize('sortOrder.filesFirst', 'Files and folders are sorted by their names. Files are displayed before folders.'), -- nls.localize('sortOrder.type', 'Files and folders are grouped by extension type then sorted by their names. Folders are displayed before files.'), -- nls.localize('sortOrder.modified', 'Files and folders are sorted by last modified date in descending order. Folders are displayed before files.'), -- nls.localize('sortOrder.foldersNestsFiles', 'Files and folders are sorted by their names. Folders are displayed before files. Files with nested children are displayed before other files.') -- ], -- 'markdownDescription': nls.localize('sortOrder', "Controls the property-based sorting of files and folders in the Explorer. When `#explorer.fileNesting.enabled#` is enabled, also controls sorting of nested files.") -- }, -- 'explorer.sortOrderLexicographicOptions': { -- 'type': 'string', -- 'enum': [LexicographicOptions.Default, LexicographicOptions.Upper, LexicographicOptions.Lower, LexicographicOptions.Unicode], -- 'default': LexicographicOptions.Default, -- 'enumDescriptions': [ -- nls.localize('sortOrderLexicographicOptions.default', 'Uppercase and lowercase names are mixed together.'), -- nls.localize('sortOrderLexicographicOptions.upper', 'Uppercase names are grouped together before lowercase names.'), -- nls.localize('sortOrderLexicographicOptions.lower', 'Lowercase names are grouped together before uppercase names.'), -- nls.localize('sortOrderLexicographicOptions.unicode', 'Names are sorted in Unicode order.') -- ], -- 'description': nls.localize('sortOrderLexicographicOptions', "Controls the lexicographic sorting of file and folder names in the Explorer.") -- }, -- 'explorer.decorations.colors': { -- type: 'boolean', -- description: nls.localize('explorer.decorations.colors', "Controls whether file decorations should use colors."), -- default: true -- }, -- 'explorer.decorations.badges': { -- type: 'boolean', -- description: nls.localize('explorer.decorations.badges', "Controls whether file decorations should use badges."), -- default: true -- }, -- 'explorer.incrementalNaming': { -- 'type': 'string', -- enum: ['simple', 'smart', 'disabled'], -- enumDescriptions: [ -- nls.localize('simple', "Appends the word \"copy\" at the end of the duplicated name potentially followed by a number."), -- nls.localize('smart', "Adds a number at the end of the duplicated name. If some number is already part of the name, tries to increase that number."), -- nls.localize('disabled', "Disables incremental naming. If two files with the same name exist you will be prompted to overwrite the existing file.") -- ], -- description: nls.localize('explorer.incrementalNaming', "Controls which naming strategy to use when giving a new name to a duplicated Explorer item on paste."), -- default: 'simple' -- }, -- 'explorer.compactFolders': { -- 'type': 'boolean', -- 'description': nls.localize('compressSingleChildFolders', "Controls whether the Explorer should render folders in a compact form. In such a form, single child folders will be compressed in a combined tree element. Useful for Java package structures, for example."), -- 'default': true -- }, -- 'explorer.copyRelativePathSeparator': { -- 'type': 'string', -- 'enum': [ -- '/', -- '\\', -- 'auto' -- ], -- 'enumDescriptions': [ -- nls.localize('copyRelativePathSeparator.slash', "Use slash as path separation character."), -- nls.localize('copyRelativePathSeparator.backslash', "Use backslash as path separation character."), -- nls.localize('copyRelativePathSeparator.auto', "Uses operating system specific path separation character."), -- ], -- 'description': nls.localize('copyRelativePathSeparator', "The path separation character used when copying relative file paths."), -- 'default': 'auto' -- }, -- 'explorer.excludeGitIgnore': { -- type: 'boolean', -- markdownDescription: nls.localize('excludeGitignore', "Controls whether entries in .gitignore should be parsed and excluded from the Explorer. Similar to {0}.", '`#files.exclude#`'), -- default: false, -- scope: ConfigurationScope.RESOURCE -- }, -- 'explorer.fileNesting.enabled': { -- 'type': 'boolean', -- scope: ConfigurationScope.RESOURCE, -- 'markdownDescription': nls.localize('fileNestingEnabled', "Controls whether file nesting is enabled in the Explorer. File nesting allows for related files in a directory to be visually grouped together under a single parent file."), -- 'default': false, -- }, -- 'explorer.fileNesting.expand': { -- 'type': 'boolean', -- 'markdownDescription': nls.localize('fileNestingExpand', "Controls whether file nests are automatically expanded. {0} must be set for this to take effect.", '`#explorer.fileNesting.enabled#`'), -- 'default': true, -- }, -- 'explorer.fileNesting.patterns': { -- 'type': 'object', -- scope: ConfigurationScope.RESOURCE, -- 'markdownDescription': nls.localize('fileNestingPatterns', "Controls nesting of files in the Explorer. {0} must be set for this to take effect. Each __Item__ represents a parent pattern and may contain a single `*` character that matches any string. Each __Value__ represents a comma separated list of the child patterns that should be shown nested under a given parent. Child patterns may contain several special tokens:\n- `${capture}`: Matches the resolved value of the `*` from the parent pattern\n- `${basename}`: Matches the parent file's basename, the `file` in `file.ts`\n- `${extname}`: Matches the parent file's extension, the `ts` in `file.ts`\n- `${dirname}`: Matches the parent file's directory name, the `src` in `src/file.ts`\n- `*`: Matches any string, may only be used once per child pattern", '`#explorer.fileNesting.enabled#`'), -- patternProperties: { -- '^[^*]*\\*?[^*]*$': { -- markdownDescription: nls.localize('fileNesting.description', "Each key pattern may contain a single `*` character which will match any string."), -- type: 'string', -- pattern: '^([^,*]*\\*?[^,*]*)(, ?[^,*]*\\*?[^,*]*)*$', -- } -- }, -- additionalProperties: false, -- 'default': { -- '*.ts': '${capture}.js', -- '*.js': '${capture}.js.map, ${capture}.min.js, ${capture}.d.ts', -- '*.jsx': '${capture}.js', -- '*.tsx': '${capture}.ts', -- 'tsconfig.json': 'tsconfig.*.json', -- 'package.json': 'package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb', -- } -- } -- } --}); -- --UndoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { -- const undoRedoService = accessor.get(IUndoRedoService); -- const explorerService = accessor.get(IExplorerService); -- const configurationService = accessor.get(IConfigurationService); -- -- const explorerCanUndo = configurationService.getValue().explorer.enableUndo; -- if (explorerService.hasViewFocus() && undoRedoService.canUndo(UNDO_REDO_SOURCE) && explorerCanUndo) { -- undoRedoService.undo(UNDO_REDO_SOURCE); -- return true; -- } -- -- return false; --}); -- --RedoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { -- const undoRedoService = accessor.get(IUndoRedoService); -- const explorerService = accessor.get(IExplorerService); -- const configurationService = accessor.get(IConfigurationService); -- -- const explorerCanUndo = configurationService.getValue().explorer.enableUndo; -- if (explorerService.hasViewFocus() && undoRedoService.canRedo(UNDO_REDO_SOURCE) && explorerCanUndo) { -- undoRedoService.redo(UNDO_REDO_SOURCE); -- return true; -- } -- -- return false; --}); -- --ModesRegistry.registerLanguage({ -- id: BINARY_TEXT_FILE_MODE, -- aliases: ['Binary'], -- mimetypes: ['text/x-code-binary'] --}); -+import './files.configuration.contribution'; -+import './files.editorPane.contribution'; -+import './files.fileEditorFactory.contribution'; -+import './files.explorer.contribution'; -diff --git a/src/vs/workbench/contrib/files/browser/files.editorPane.contribution.ts b/src/vs/workbench/contrib/files/browser/files.editorPane.contribution.ts -new file mode 100644 -index 00000000000..18a1975b685 ---- /dev/null -+++ b/src/vs/workbench/contrib/files/browser/files.editorPane.contribution.ts -@@ -0,0 +1,94 @@ -+/*--------------------------------------------------------------------------------------------- -+ * Copyright (c) Microsoft Corporation. All rights reserved. -+ * Licensed under the MIT License. See License.txt in the project root for license information. -+ *--------------------------------------------------------------------------------------------*/ -+ -+import * as nls from 'vs/nls'; -+import { sep } from 'vs/base/common/path'; -+import { Registry } from 'vs/platform/registry/common/platform'; -+import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; -+import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; -+import { FILE_EDITOR_INPUT_ID, BINARY_TEXT_FILE_MODE } from 'vs/workbench/contrib/files/common/files'; -+import { TextFileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/textFileEditorTracker'; -+import { TextFileSaveErrorHandler } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; -+import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; -+import { BinaryFileEditor } from 'vs/workbench/contrib/files/browser/editors/binaryFileEditor'; -+import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -+import { isWindows } from 'vs/base/common/platform'; -+import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/editor'; -+import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -+import { ILabelService } from 'vs/platform/label/common/label'; -+import { Schemas } from 'vs/base/common/network'; -+import { WorkspaceWatcher } from 'vs/workbench/contrib/files/browser/workspaceWatcher'; -+import { DirtyFilesIndicator } from 'vs/workbench/contrib/files/common/dirtyFilesIndicator'; -+import { FileEditorInputSerializer, FileEditorWorkingCopyEditorHandler } from 'vs/workbench/contrib/files/browser/editors/fileEditorHandler'; -+import { ModesRegistry } from 'vs/editor/common/languages/modesRegistry'; -+import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; -+import './files.fileEditorFactory.contribution'; -+ -+class FileUriLabelContribution implements IWorkbenchContribution { -+ -+ static readonly ID = 'workbench.contrib.fileUriLabel'; -+ -+ constructor(@ILabelService labelService: ILabelService) { -+ labelService.registerFormatter({ -+ scheme: Schemas.file, -+ formatting: { -+ label: '${authority}${path}', -+ separator: sep, -+ tildify: !isWindows, -+ normalizeDriveLetter: isWindows, -+ authorityPrefix: sep + sep, -+ workspaceSuffix: '' -+ } -+ }); -+ } -+} -+// Register file editors -+ -+Registry.as(EditorExtensions.EditorPane).registerEditorPane( -+ EditorPaneDescriptor.create( -+ TextFileEditor, -+ TextFileEditor.ID, -+ nls.localize('textFileEditor', "Text File Editor") -+ ), -+ [ -+ new SyncDescriptor(FileEditorInput) -+ ] -+); -+ -+Registry.as(EditorExtensions.EditorPane).registerEditorPane( -+ EditorPaneDescriptor.create( -+ BinaryFileEditor, -+ BinaryFileEditor.ID, -+ nls.localize('binaryFileEditor', "Binary File Editor") -+ ), -+ [ -+ new SyncDescriptor(FileEditorInput) -+ ] -+); -+ -+// Register Editor Input Serializer & Handler -+Registry.as(EditorExtensions.EditorFactory).registerEditorSerializer(FILE_EDITOR_INPUT_ID, FileEditorInputSerializer); -+registerWorkbenchContribution2(FileEditorWorkingCopyEditorHandler.ID, FileEditorWorkingCopyEditorHandler, WorkbenchPhase.BlockRestore); -+ -+// Register Text File Editor Tracker -+registerWorkbenchContribution2(TextFileEditorTracker.ID, TextFileEditorTracker, WorkbenchPhase.BlockStartup); -+ -+// Register Text File Save Error Handler -+registerWorkbenchContribution2(TextFileSaveErrorHandler.ID, TextFileSaveErrorHandler, WorkbenchPhase.BlockStartup); -+ -+// Register uri display for file uris -+registerWorkbenchContribution2(FileUriLabelContribution.ID, FileUriLabelContribution, WorkbenchPhase.BlockStartup); -+ -+// Register Workspace Watcher -+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored); -+ -+// Register Dirty Files Indicator -+registerWorkbenchContribution2(DirtyFilesIndicator.ID, DirtyFilesIndicator, WorkbenchPhase.BlockStartup); -+ -+ModesRegistry.registerLanguage({ -+ id: BINARY_TEXT_FILE_MODE, -+ aliases: ['Binary'], -+ mimetypes: ['text/x-code-binary'] -+}); -diff --git a/src/vs/workbench/contrib/files/browser/files.explorer.contribution.ts b/src/vs/workbench/contrib/files/browser/files.explorer.contribution.ts -new file mode 100644 -index 00000000000..0ed00cb19e7 ---- /dev/null -+++ b/src/vs/workbench/contrib/files/browser/files.explorer.contribution.ts -@@ -0,0 +1,270 @@ -+/*--------------------------------------------------------------------------------------------- -+ * Copyright (c) Microsoft Corporation. All rights reserved. -+ * Licensed under the MIT License. See License.txt in the project root for license information. -+ *--------------------------------------------------------------------------------------------*/ -+ -+import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; -+import * as nls from 'vs/nls'; -+import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -+import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; -+import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -+import { Registry } from 'vs/platform/registry/common/platform'; -+import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; -+import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; -+import { ExplorerService, UNDO_REDO_SOURCE } from 'vs/workbench/contrib/files/browser/explorerService'; -+import { ExplorerViewletViewsContribution } from 'vs/workbench/contrib/files/browser/explorerViewlet'; -+import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; -+import { IFilesConfiguration, LexicographicOptions, SortOrder, UndoConfirmLevel } from 'vs/workbench/contrib/files/common/files'; -+import './files.configuration.contribution'; -+import './files.editorPane.contribution'; -+import './files.fileEditorFactory.contribution'; -+ -+registerSingleton(IExplorerService, ExplorerService, InstantiationType.Delayed); -+ -+// Register Explorer views -+registerWorkbenchContribution2(ExplorerViewletViewsContribution.ID, ExplorerViewletViewsContribution, WorkbenchPhase.BlockStartup); -+ -+// Configuration -+const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); -+ -+configurationRegistry.registerConfiguration({ -+ 'id': 'explorer', -+ 'order': 10, -+ 'title': nls.localize('explorerConfigurationTitle', "File Explorer"), -+ 'type': 'object', -+ 'properties': { -+ 'explorer.openEditors.visible': { -+ 'type': 'number', -+ 'description': nls.localize({ key: 'openEditorsVisible', comment: ['Open is an adjective'] }, "The initial maximum number of editors shown in the Open Editors pane. Exceeding this limit will show a scroll bar and allow resizing the pane to display more items."), -+ 'default': 9, -+ 'minimum': 1 -+ }, -+ 'explorer.openEditors.minVisible': { -+ 'type': 'number', -+ 'description': nls.localize({ key: 'openEditorsVisibleMin', comment: ['Open is an adjective'] }, "The minimum number of editor slots pre-allocated in the Open Editors pane. If set to 0 the Open Editors pane will dynamically resize based on the number of editors."), -+ 'default': 0, -+ 'minimum': 0 -+ }, -+ 'explorer.openEditors.sortOrder': { -+ 'type': 'string', -+ 'enum': ['editorOrder', 'alphabetical', 'fullPath'], -+ 'description': nls.localize({ key: 'openEditorsSortOrder', comment: ['Open is an adjective'] }, "Controls the sorting order of editors in the Open Editors pane."), -+ 'enumDescriptions': [ -+ nls.localize('sortOrder.editorOrder', 'Editors are ordered in the same order editor tabs are shown.'), -+ nls.localize('sortOrder.alphabetical', 'Editors are ordered alphabetically by tab name inside each editor group.'), -+ nls.localize('sortOrder.fullPath', 'Editors are ordered alphabetically by full path inside each editor group.') -+ ], -+ 'default': 'editorOrder' -+ }, -+ 'explorer.autoReveal': { -+ 'type': ['boolean', 'string'], -+ 'enum': [true, false, 'focusNoScroll'], -+ 'default': true, -+ 'enumDescriptions': [ -+ nls.localize('autoReveal.on', 'Files will be revealed and selected.'), -+ nls.localize('autoReveal.off', 'Files will not be revealed and selected.'), -+ nls.localize('autoReveal.focusNoScroll', 'Files will not be scrolled into view, but will still be focused.'), -+ ], -+ 'description': nls.localize('autoReveal', "Controls whether the Explorer should automatically reveal and select files when opening them.") -+ }, -+ 'explorer.autoRevealExclude': { -+ 'type': 'object', -+ 'markdownDescription': nls.localize('autoRevealExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) for excluding files and folders from being revealed and selected in the Explorer when they are opened. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths."), -+ 'default': { '**/node_modules': true, '**/bower_components': true }, -+ 'additionalProperties': { -+ 'anyOf': [ -+ { -+ 'type': 'boolean', -+ 'description': nls.localize('explorer.autoRevealExclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), -+ }, -+ { -+ type: 'object', -+ properties: { -+ when: { -+ type: 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) -+ pattern: '\\w*\\$\\(basename\\)\\w*', -+ default: '$(basename).ext', -+ description: nls.localize('explorer.autoRevealExclude.when', 'Additional check on the siblings of a matching file. Use $(basename) as variable for the matching file name.') -+ } -+ } -+ } -+ ] -+ } -+ }, -+ 'explorer.enableDragAndDrop': { -+ 'type': 'boolean', -+ 'description': nls.localize('enableDragAndDrop', "Controls whether the Explorer should allow to move files and folders via drag and drop. This setting only effects drag and drop from inside the Explorer."), -+ 'default': true -+ }, -+ 'explorer.confirmDragAndDrop': { -+ 'type': 'boolean', -+ 'description': nls.localize('confirmDragAndDrop', "Controls whether the Explorer should ask for confirmation to move files and folders via drag and drop."), -+ 'default': true -+ }, -+ 'explorer.confirmPasteNative': { -+ 'type': 'boolean', -+ 'description': nls.localize('confirmPasteNative', "Controls whether the Explorer should ask for confirmation when pasting native files and folders."), -+ 'default': true -+ }, -+ 'explorer.confirmDelete': { -+ 'type': 'boolean', -+ 'description': nls.localize('confirmDelete', "Controls whether the Explorer should ask for confirmation when deleting a file via the trash."), -+ 'default': true -+ }, -+ 'explorer.enableUndo': { -+ 'type': 'boolean', -+ 'description': nls.localize('enableUndo', "Controls whether the Explorer should support undoing file and folder operations."), -+ 'default': true -+ }, -+ 'explorer.confirmUndo': { -+ 'type': 'string', -+ 'enum': [UndoConfirmLevel.Verbose, UndoConfirmLevel.Default, UndoConfirmLevel.Light], -+ 'description': nls.localize('confirmUndo', "Controls whether the Explorer should ask for confirmation when undoing."), -+ 'default': UndoConfirmLevel.Default, -+ 'enumDescriptions': [ -+ nls.localize('enableUndo.verbose', 'Explorer will prompt before all undo operations.'), -+ nls.localize('enableUndo.default', 'Explorer will prompt before destructive undo operations.'), -+ nls.localize('enableUndo.light', 'Explorer will not prompt before undo operations when focused.'), -+ ], -+ }, -+ 'explorer.expandSingleFolderWorkspaces': { -+ 'type': 'boolean', -+ 'description': nls.localize('expandSingleFolderWorkspaces', "Controls whether the Explorer should expand multi-root workspaces containing only one folder during initialization"), -+ 'default': true -+ }, -+ 'explorer.sortOrder': { -+ 'type': 'string', -+ 'enum': [SortOrder.Default, SortOrder.Mixed, SortOrder.FilesFirst, SortOrder.Type, SortOrder.Modified, SortOrder.FoldersNestsFiles], -+ 'default': SortOrder.Default, -+ 'enumDescriptions': [ -+ nls.localize('sortOrder.default', 'Files and folders are sorted by their names. Folders are displayed before files.'), -+ nls.localize('sortOrder.mixed', 'Files and folders are sorted by their names. Files are interwoven with folders.'), -+ nls.localize('sortOrder.filesFirst', 'Files and folders are sorted by their names. Files are displayed before folders.'), -+ nls.localize('sortOrder.type', 'Files and folders are grouped by extension type then sorted by their names. Folders are displayed before files.'), -+ nls.localize('sortOrder.modified', 'Files and folders are sorted by last modified date in descending order. Folders are displayed before files.'), -+ nls.localize('sortOrder.foldersNestsFiles', 'Files and folders are sorted by their names. Folders are displayed before files. Files with nested children are displayed before other files.') -+ ], -+ 'markdownDescription': nls.localize('sortOrder', "Controls the property-based sorting of files and folders in the Explorer. When `#explorer.fileNesting.enabled#` is enabled, also controls sorting of nested files.") -+ }, -+ 'explorer.sortOrderLexicographicOptions': { -+ 'type': 'string', -+ 'enum': [LexicographicOptions.Default, LexicographicOptions.Upper, LexicographicOptions.Lower, LexicographicOptions.Unicode], -+ 'default': LexicographicOptions.Default, -+ 'enumDescriptions': [ -+ nls.localize('sortOrderLexicographicOptions.default', 'Uppercase and lowercase names are mixed together.'), -+ nls.localize('sortOrderLexicographicOptions.upper', 'Uppercase names are grouped together before lowercase names.'), -+ nls.localize('sortOrderLexicographicOptions.lower', 'Lowercase names are grouped together before uppercase names.'), -+ nls.localize('sortOrderLexicographicOptions.unicode', 'Names are sorted in Unicode order.') -+ ], -+ 'description': nls.localize('sortOrderLexicographicOptions', "Controls the lexicographic sorting of file and folder names in the Explorer.") -+ }, -+ 'explorer.decorations.colors': { -+ type: 'boolean', -+ description: nls.localize('explorer.decorations.colors', "Controls whether file decorations should use colors."), -+ default: true -+ }, -+ 'explorer.decorations.badges': { -+ type: 'boolean', -+ description: nls.localize('explorer.decorations.badges', "Controls whether file decorations should use badges."), -+ default: true -+ }, -+ 'explorer.incrementalNaming': { -+ 'type': 'string', -+ enum: ['simple', 'smart', 'disabled'], -+ enumDescriptions: [ -+ nls.localize('simple', "Appends the word \"copy\" at the end of the duplicated name potentially followed by a number."), -+ nls.localize('smart', "Adds a number at the end of the duplicated name. If some number is already part of the name, tries to increase that number."), -+ nls.localize('disabled', "Disables incremental naming. If two files with the same name exist you will be prompted to overwrite the existing file.") -+ ], -+ description: nls.localize('explorer.incrementalNaming', "Controls which naming strategy to use when giving a new name to a duplicated Explorer item on paste."), -+ default: 'simple' -+ }, -+ 'explorer.compactFolders': { -+ 'type': 'boolean', -+ 'description': nls.localize('compressSingleChildFolders', "Controls whether the Explorer should render folders in a compact form. In such a form, single child folders will be compressed in a combined tree element. Useful for Java package structures, for example."), -+ 'default': true -+ }, -+ 'explorer.copyRelativePathSeparator': { -+ 'type': 'string', -+ 'enum': [ -+ '/', -+ '\\', -+ 'auto' -+ ], -+ 'enumDescriptions': [ -+ nls.localize('copyRelativePathSeparator.slash', "Use slash as path separation character."), -+ nls.localize('copyRelativePathSeparator.backslash', "Use backslash as path separation character."), -+ nls.localize('copyRelativePathSeparator.auto', "Uses operating system specific path separation character."), -+ ], -+ 'description': nls.localize('copyRelativePathSeparator', "The path separation character used when copying relative file paths."), -+ 'default': 'auto' -+ }, -+ 'explorer.excludeGitIgnore': { -+ type: 'boolean', -+ markdownDescription: nls.localize('excludeGitignore', "Controls whether entries in .gitignore should be parsed and excluded from the Explorer. Similar to {0}.", '`#files.exclude#`'), -+ default: false, -+ scope: ConfigurationScope.RESOURCE -+ }, -+ 'explorer.fileNesting.enabled': { -+ 'type': 'boolean', -+ scope: ConfigurationScope.RESOURCE, -+ 'markdownDescription': nls.localize('fileNestingEnabled', "Controls whether file nesting is enabled in the Explorer. File nesting allows for related files in a directory to be visually grouped together under a single parent file."), -+ 'default': false, -+ }, -+ 'explorer.fileNesting.expand': { -+ 'type': 'boolean', -+ 'markdownDescription': nls.localize('fileNestingExpand', "Controls whether file nests are automatically expanded. {0} must be set for this to take effect.", '`#explorer.fileNesting.enabled#`'), -+ 'default': true, -+ }, -+ 'explorer.fileNesting.patterns': { -+ 'type': 'object', -+ scope: ConfigurationScope.RESOURCE, -+ 'markdownDescription': nls.localize('fileNestingPatterns', "Controls nesting of files in the Explorer. {0} must be set for this to take effect. Each __Item__ represents a parent pattern and may contain a single `*` character that matches any string. Each __Value__ represents a comma separated list of the child patterns that should be shown nested under a given parent. Child patterns may contain several special tokens:\n- `${capture}`: Matches the resolved value of the `*` from the parent pattern\n- `${basename}`: Matches the parent file's basename, the `file` in `file.ts`\n- `${extname}`: Matches the parent file's extension, the `ts` in `file.ts`\n- `${dirname}`: Matches the parent file's directory name, the `src` in `src/file.ts`\n- `*`: Matches any string, may only be used once per child pattern", '`#explorer.fileNesting.enabled#`'), -+ patternProperties: { -+ '^[^*]*\\*?[^*]*$': { -+ markdownDescription: nls.localize('fileNesting.description', "Each key pattern may contain a single `*` character which will match any string."), -+ type: 'string', -+ pattern: '^([^,*]*\\*?[^,*]*)(, ?[^,*]*\\*?[^,*]*)*$', -+ } -+ }, -+ additionalProperties: false, -+ 'default': { -+ '*.ts': '${capture}.js', -+ '*.js': '${capture}.js.map, ${capture}.min.js, ${capture}.d.ts', -+ '*.jsx': '${capture}.js', -+ '*.tsx': '${capture}.ts', -+ 'tsconfig.json': 'tsconfig.*.json', -+ 'package.json': 'package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb', -+ } -+ } -+ } -+}); -+ -+UndoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { -+ const undoRedoService = accessor.get(IUndoRedoService); -+ const explorerService = accessor.get(IExplorerService); -+ const configurationService = accessor.get(IConfigurationService); -+ -+ const explorerCanUndo = configurationService.getValue().explorer.enableUndo; -+ if (explorerService.hasViewFocus() && undoRedoService.canUndo(UNDO_REDO_SOURCE) && explorerCanUndo) { -+ undoRedoService.undo(UNDO_REDO_SOURCE); -+ return true; -+ } -+ -+ return false; -+}); -+ -+RedoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { -+ const undoRedoService = accessor.get(IUndoRedoService); -+ const explorerService = accessor.get(IExplorerService); -+ const configurationService = accessor.get(IConfigurationService); -+ -+ const explorerCanUndo = configurationService.getValue().explorer.enableUndo; -+ if (explorerService.hasViewFocus() && undoRedoService.canRedo(UNDO_REDO_SOURCE) && explorerCanUndo) { -+ undoRedoService.redo(UNDO_REDO_SOURCE); -+ return true; -+ } -+ -+ return false; -+}); -diff --git a/src/vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution.ts b/src/vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution.ts -new file mode 100644 -index 00000000000..2f31d6a7984 ---- /dev/null -+++ b/src/vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution.ts -@@ -0,0 +1,23 @@ -+/*--------------------------------------------------------------------------------------------- -+ * Copyright (c) Microsoft Corporation. All rights reserved. -+ * Licensed under the MIT License. See License.txt in the project root for license information. -+ *--------------------------------------------------------------------------------------------*/ -+ -+import { Registry } from 'vs/platform/registry/common/platform'; -+import { EditorExtensions, IEditorFactoryRegistry, IFileEditorInput } from 'vs/workbench/common/editor'; -+import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; -+import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files'; -+ -+// Register default file input factory -+Registry.as(EditorExtensions.EditorFactory).registerFileEditorFactory({ -+ -+ typeId: FILE_EDITOR_INPUT_ID, -+ -+ createFileEditor: (resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents, instantiationService): IFileEditorInput => { -+ return instantiationService.createInstance(FileEditorInput, resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents); -+ }, -+ -+ isFileEditor: (obj): obj is IFileEditorInput => { -+ return obj instanceof FileEditorInput; -+ } -+}); -diff --git a/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts b/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts -index 9feccec6965..64b9e5d3ed0 100644 ---- a/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts -+++ b/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts -@@ -33,7 +33,7 @@ export interface IDefaultLogLevelsService { - migrateLogLevels(): void; - } - --class DefaultLogLevelsService implements IDefaultLogLevelsService { -+export class DefaultLogLevelsService implements IDefaultLogLevelsService { - - _serviceBrand: undefined; - -diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts -index 84bde0d8006..941c88582cb 100644 ---- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts -+++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts -@@ -83,7 +83,6 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history'; - import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; - import { IPathService } from 'vs/workbench/services/path/common/pathService'; - import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; --import { importAMDNodeModule } from 'vs/amdX'; - import type { IMarker, Terminal as XTermTerminal } from '@xterm/xterm'; - import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands'; - import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; -@@ -703,7 +702,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { - return xtermConstructor; - } - xtermConstructor = Promises.withAsyncBody(async (resolve) => { -- const Terminal = (await importAMDNodeModule('@xterm/xterm', 'lib/xterm.js')).Terminal; -+ const Terminal = (await import('@xterm/xterm')).Terminal; - // Localize strings - Terminal.strings.promptLabel = nls.localize('terminal.integrated.a11yPromptLabel', 'Terminal input'); - Terminal.strings.tooMuchOutput = keybinding ? nls.localize('terminal.integrated.useAccessibleBuffer', 'Use the accessible buffer {0} to manually review output', keybinding.getLabel()) : nls.localize('terminal.integrated.useAccessibleBufferNoKb', 'Use the Terminal: Focus Accessible Buffer command to manually review output'); -diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts -index f78008e14db..5cf622e0620 100644 ---- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts -+++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts -@@ -19,7 +19,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c - import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; - import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; - import { INotificationService } from 'vs/platform/notification/common/notification'; --import { ICreateContributedTerminalProfileOptions, IExtensionTerminalProfile, IPtyHostAttachTarget, IRawTerminalInstanceLayoutInfo, IRawTerminalTabLayoutInfo, IShellLaunchConfig, ITerminalBackend, ITerminalLaunchError, ITerminalLogService, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalExitReason, TerminalLocation, TerminalLocationString, TitleEventSource } from 'vs/platform/terminal/common/terminal'; -+import { ICreateContributedTerminalProfileOptions, IExtensionTerminalProfile, IPtyHostAttachTarget, IRawTerminalInstanceLayoutInfo, IRawTerminalTabLayoutInfo, IShellLaunchConfig, ITerminalBackend, ITerminalBackendRegistry, ITerminalLaunchError, ITerminalLogService, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalExitReason, TerminalExtensions, TerminalLocation, TerminalLocationString, TitleEventSource } from 'vs/platform/terminal/common/terminal'; - import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings'; - import { iconForeground } from 'vs/platform/theme/common/colorRegistry'; - import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry'; -@@ -54,6 +54,7 @@ import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilitie - import { ITimerService } from 'vs/workbench/services/timer/browser/timerService'; - import { mark } from 'vs/base/common/performance'; - import { DetachedTerminal } from 'vs/workbench/contrib/terminal/browser/detachedTerminal'; -+import { Registry } from 'vs/platform/registry/common/platform'; - import { ITerminalCapabilityImplMap, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; - import { createInstanceCapabilityEventMultiplexer } from 'vs/workbench/contrib/terminal/browser/terminalEvents'; - import { mainWindow } from 'vs/base/browser/window'; -@@ -216,7 +217,7 @@ export class TerminalService extends Disposable implements ITerminalService { - this._handleInstanceContextKeys(); - this._terminalShellTypeContextKey = TerminalContextKeys.shellType.bindTo(this._contextKeyService); - this._processSupportContextKey = TerminalContextKeys.processSupported.bindTo(this._contextKeyService); -- this._processSupportContextKey.set(!isWeb || this._remoteAgentService.getConnection() !== null); -+ this._processSupportContextKey.set(!isWeb || this._remoteAgentService.getConnection() !== null || Registry.as(TerminalExtensions.Backend).getTerminalBackend() !== undefined); - this._terminalHasBeenCreated = TerminalContextKeys.terminalHasBeenCreated.bindTo(this._contextKeyService); - this._terminalCountContextKey = TerminalContextKeys.count.bindTo(this._contextKeyService); - this._terminalEditorActive = TerminalContextKeys.terminalEditorActive.bindTo(this._contextKeyService); -diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts -index 0f2ef8f01f4..a0d82d41170 100644 ---- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts -+++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts -@@ -35,7 +35,6 @@ import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/dec - import { ITerminalCapabilityStore, ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; - import { Emitter } from 'vs/base/common/event'; - import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; --import { importAMDNodeModule } from 'vs/amdX'; - import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; - import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; - import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -@@ -754,7 +753,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach - - protected async _getCanvasAddonConstructor(): Promise { - if (!CanvasAddon) { -- CanvasAddon = (await importAMDNodeModule('@xterm/addon-canvas', 'lib/xterm-addon-canvas.js')).CanvasAddon; -+ CanvasAddon = (await import('@xterm/addon-canvas')).CanvasAddon; - } - return CanvasAddon; - } -@@ -780,35 +779,35 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach - - protected async _getImageAddonConstructor(): Promise { - if (!ImageAddon) { -- ImageAddon = (await importAMDNodeModule('@xterm/addon-image', 'lib/addon-image.js')).ImageAddon; -+ ImageAddon = (await import('@xterm/addon-image')).ImageAddon; - } - return ImageAddon; - } - - protected async _getSearchAddonConstructor(): Promise { - if (!SearchAddon) { -- SearchAddon = (await importAMDNodeModule('@xterm/addon-search', 'lib/addon-search.js')).SearchAddon; -+ SearchAddon = (await import('@xterm/addon-search')).SearchAddon; - } - return SearchAddon; - } - - protected async _getUnicode11Constructor(): Promise { - if (!Unicode11Addon) { -- Unicode11Addon = (await importAMDNodeModule('@xterm/addon-unicode11', 'lib/addon-unicode11.js')).Unicode11Addon; -+ Unicode11Addon = (await import('@xterm/addon-unicode11')).Unicode11Addon; - } - return Unicode11Addon; - } - - protected async _getWebglAddonConstructor(): Promise { - if (!WebglAddon) { -- WebglAddon = (await importAMDNodeModule('@xterm/addon-webgl', 'lib/addon-webgl.js')).WebglAddon; -+ WebglAddon = (await import('@xterm/addon-webgl')).WebglAddon; - } - return WebglAddon; - } - - protected async _getSerializeAddonConstructor(): Promise { - if (!SerializeAddon) { -- SerializeAddon = (await importAMDNodeModule('@xterm/addon-serialize', 'lib/addon-serialize.js')).SerializeAddon; -+ SerializeAddon = (await import('@xterm/addon-serialize')).SerializeAddon; - } - return SerializeAddon; - } -diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts -index 8868f63beef..6aaa5c0c2df 100644 ---- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts -+++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts -@@ -5,7 +5,6 @@ - import type { CanvasAddon as CanvasAddonType } from '@xterm/addon-canvas'; - import type { SerializeAddon as SerializeAddonType } from '@xterm/addon-serialize'; - import type { IBufferLine, IMarker, ITerminalOptions, ITheme, Terminal as RawXtermTerminal, Terminal as XTermTerminal } from '@xterm/xterm'; --import { importAMDNodeModule } from 'vs/amdX'; - import { $, addDisposableListener, addStandardDisposableListener, getWindow } from 'vs/base/browser/dom'; - import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; - import { debounce, memoize, throttle } from 'vs/base/common/decorators'; -@@ -467,13 +466,13 @@ export class TerminalStickyScrollOverlay extends Disposable { - - @memoize - private async _getCanvasAddonConstructor(): Promise { -- const m = await importAMDNodeModule('@xterm/addon-canvas', 'lib/xterm-addon-canvas.js'); -+ const m = await import('@xterm/addon-canvas'); - return m.CanvasAddon; - } - - @memoize - private async _getSerializeAddonConstructor(): Promise { -- const m = await importAMDNodeModule('@xterm/addon-serialize', 'lib/addon-serialize.js'); -+ const m = await import('@xterm/addon-serialize'); - return m.SerializeAddon; - } - } -diff --git a/src/vs/workbench/contrib/webview/browser/pre/service-worker.js b/src/vs/workbench/contrib/webview/browser/pre/service-worker.js -index a6e9943b866..c470a1c9ed5 100644 ---- a/src/vs/workbench/contrib/webview/browser/pre/service-worker.js -+++ b/src/vs/workbench/contrib/webview/browser/pre/service-worker.js -@@ -452,7 +452,6 @@ async function getOuterIframeClient(webviewId) { - const allClients = await sw.clients.matchAll({ includeUncontrolled: true }); - return allClients.filter(client => { - const clientUrl = new URL(client.url); -- const hasExpectedPathName = (clientUrl.pathname === `${rootPath}/` || clientUrl.pathname === `${rootPath}/index.html` || clientUrl.pathname === `${rootPath}/index-no-csp.html`); -- return hasExpectedPathName && clientUrl.searchParams.get('id') === webviewId; -+ return clientUrl.searchParams.get('id') === webviewId; - }); - } -diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts -index 6514979da3d..e05a401c479 100644 ---- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts -+++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts -@@ -11,7 +11,7 @@ import { streamToBuffer, VSBufferReadableStream } from 'vs/base/common/buffer'; - import { CancellationTokenSource } from 'vs/base/common/cancellation'; - import { Emitter, Event } from 'vs/base/common/event'; - import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; --import { COI } from 'vs/base/common/network'; -+import { COI, FileAccess } from 'vs/base/common/network'; - import { URI } from 'vs/base/common/uri'; - import { generateUuid } from 'vs/base/common/uuid'; - import { localize } from 'vs/nls'; -@@ -185,11 +185,6 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD - return; - } - -- if (e.origin !== this._webviewContentOrigin(this._encodedWebviewOrigin)) { -- console.log(`Skipped renderer receiving message due to mismatched origins: ${e.origin} ${this._webviewContentOrigin}`); -- return; -- } -- - if (e.data.channel === 'webview-ready') { - if (this._messagePort) { - return; -@@ -475,6 +470,9 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD - params.purpose = options.purpose; - } - -+ params.serviceWorkerUri = FileAccess.asBrowserUri('vs/workbench/contrib/webview/browser/pre/service-worker.js').toString(true); -+ params.fakeHtmlUri = FileAccess.asBrowserUri('vs/workbench/contrib/webview/browser/pre/fake.html').toString(true); -+ - COI.addSearchParam(params, true, true); - - const queryString = new URLSearchParams(params).toString(); -@@ -482,7 +480,8 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD - // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1754872 - const fileName = isFirefox ? 'index-no-csp.html' : 'index.html'; - -- this.element!.setAttribute('src', `${this.webviewContentEndpoint(encodedWebviewOrigin)}/${fileName}?${queryString}`); -+ const relativeIframeSrc = FileAccess.asBrowserUri(`vs/workbench/contrib/webview/browser/pre/${fileName}`); -+ this.element!.setAttribute('src', `${relativeIframeSrc.toString(true)}?${queryString}`); - } - - public mountTo(element: HTMLElement) { -@@ -536,11 +535,6 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD - return endpoint; - } - -- private _webviewContentOrigin(encodedWebviewOrigin: string): string { -- const uri = URI.parse(this.webviewContentEndpoint(encodedWebviewOrigin)); -- return uri.scheme + '://' + uri.authority.toLowerCase(); -- } -- - private doPostMessage(channel: string, data?: any, transferable: Transferable[] = []): boolean { - if (this.element && this._messagePort) { - this._messagePort.postMessage({ channel, args: data }, transferable); -diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts -index 869f44526b4..296ac140860 100644 ---- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts -+++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts -@@ -17,6 +17,7 @@ import { IFileService } from 'vs/platform/files/common/files'; - import { INotificationService } from 'vs/platform/notification/common/notification'; - import { ILanguageService } from 'vs/editor/common/languages/language'; - import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -+import { AppResourcePath, FileAccess } from 'vs/base/common/network'; - - - export class GettingStartedDetailsRenderer { -@@ -221,12 +222,9 @@ export class GettingStartedDetailsRenderer { - try { - const moduleId = JSON.parse(path.query).moduleId; - if (useModuleId && moduleId) { -- const contents = await new Promise(c => { -- require([moduleId], content => { -- c(content.default()); -- }); -- }); -- return contents; -+ const content = await FileAccess.toModuleContent<() => Promise>(moduleId); -+ -+ return content(); - } - } catch { } - -@@ -262,7 +260,7 @@ export class GettingStartedDetailsRenderer { - } - - const transformUri = (src: string, base: URI) => { -- const path = joinPath(base, src); -+ const path = FileAccess.asBrowserUri(joinPath(base, src).fsPath.slice(1) as AppResourcePath); - return asWebviewUri(path).toString(true); - }; - -diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts -index 8a068851f28..eb4ed86bd31 100644 ---- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts -+++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts -@@ -33,7 +33,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; - import { checkGlobFileExists } from 'vs/workbench/services/extensions/common/workspaceContains'; - import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; - import { CancellationTokenSource } from 'vs/base/common/cancellation'; --import { DefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -+import { getDefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; - - export const HasMultipleNewFileEntries = new RawContextKey('hasMultipleNewFileEntries', false); - -@@ -396,7 +396,7 @@ export class WalkthroughsService extends Disposable implements IWalkthroughsServ - type: 'image', - path: iconStr - ? FileAccess.uriToBrowserUri(joinPath(extension.extensionLocation, iconStr)).toString(true) -- : DefaultIconPath -+ : getDefaultIconPath() - }, - when: ContextKeyExpr.deserialize(override ?? walkthrough.when) ?? ContextKeyExpr.true(), - } as const; -diff --git a/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts b/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts -index 24764f1e31a..e16d9f5afcd 100644 ---- a/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts -+++ b/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts -@@ -10,13 +10,13 @@ import { ITextModel, DefaultEndOfLine, EndOfLinePreference, ITextBufferFactory } - import { ILanguageService } from 'vs/editor/common/languages/language'; - import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; - import { marked } from 'vs/base/common/marked/marked'; --import { Schemas } from 'vs/base/common/network'; -+import { FileAccess, Schemas } from 'vs/base/common/network'; - import { Range } from 'vs/editor/common/core/range'; - import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; - import { assertIsDefined } from 'vs/base/common/types'; --import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -+import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; - --export function requireToContent(instantiationService: IInstantiationService, resource: URI): Promise { -+export async function requireToContent(instantiationService: IInstantiationService, resource: URI): Promise { - if (!resource.query) { - throw new Error('Welcome: invalid resource'); - } -@@ -26,17 +26,9 @@ export function requireToContent(instantiationService: IInstantiationService, re - throw new Error('Welcome: invalid resource'); - } - -- const content: Promise = new Promise((resolve, reject) => { -- require([query.moduleId], content => { -- try { -- resolve(instantiationService.invokeFunction(content.default)); -- } catch (err) { -- reject(err); -- } -- }); -- }); -+ const content = await FileAccess.toModuleContent<(accessor: ServicesAccessor) => Promise>(query.moduleId); - -- return content; -+ return instantiationService.invokeFunction(content); - } - - export class WalkThroughSnippetContentProvider implements ITextModelContentProvider, IWorkbenchContribution { -diff --git a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts -index ce6f32b0914..4fe4fb39bd7 100644 ---- a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts -+++ b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts -@@ -302,13 +302,6 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili - } - - protected patchMethods(auxiliaryWindow: CodeWindow): void { -- -- // Disallow `createElement` because it would create -- // HTML Elements in the "wrong" context and break -- // code that does "instanceof HTMLElement" etc. -- auxiliaryWindow.document.createElement = function () { -- throw new Error('Not allowed to create elements in child window JavaScript context. Always use the main window so that "xyz instanceof HTMLElement" continues to work.'); -- }; - } - - private applyMeta(auxiliaryWindow: CodeWindow): void { -diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts -index caf3def4700..232570b93fa 100644 ---- a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts -+++ b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts -@@ -65,7 +65,7 @@ class BisectState { - ) { } - } - --class ExtensionBisectService implements IExtensionBisectService { -+export class ExtensionBisectService implements IExtensionBisectService { - - declare readonly _serviceBrand: undefined; - -diff --git a/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts b/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts -index 0e60b30cd13..a8fef74dbc4 100644 ---- a/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts -+++ b/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts -@@ -27,7 +27,7 @@ interface IExtensionFeatureState { - - const FEATURES_STATE_KEY = 'extension.features.state'; - --class ExtensionFeaturesManagementService extends Disposable implements IExtensionFeaturesManagementService { -+export class ExtensionFeaturesManagementService extends Disposable implements IExtensionFeaturesManagementService { - declare readonly _serviceBrand: undefined; - - private readonly _onDidChangeEnablement = this._register(new Emitter<{ extension: ExtensionIdentifier; featureId: string; enabled: boolean }>()); -diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts -index 362e485948a..50f5a5f175d 100644 ---- a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts -+++ b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts -@@ -39,7 +39,7 @@ export interface IExtensionManagementServerService { - getExtensionInstallLocation(extension: IExtension): ExtensionInstallLocation | null; - } - --export const DefaultIconPath = FileAccess.asBrowserUri('vs/workbench/services/extensionManagement/common/media/defaultIcon.png').toString(true); -+export const getDefaultIconPath = () => FileAccess.asBrowserUri('vs/workbench/services/extensionManagement/common/media/defaultIcon.png').toString(true); - - export type InstallExtensionOnServerEvent = InstallExtensionEvent & { server: IExtensionManagementServer }; - export type UninstallExtensionOnServerEvent = UninstallExtensionEvent & { server: IExtensionManagementServer }; -diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts -index a181772e8c4..0b12e5972ce 100644 ---- a/src/vs/workbench/services/extensions/browser/extensionService.ts -+++ b/src/vs/workbench/services/extensions/browser/extensionService.ts -@@ -43,8 +43,10 @@ import { IUserDataInitializationService } from 'vs/workbench/services/userData/b - import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; - - export class ExtensionService extends AbstractExtensionService implements IExtensionService { -- - constructor( -+ extensionsProposedApi: ExtensionsProposedApi, -+ extensionHostFactory: IExtensionHostFactory, -+ extensionHostKindPicker: IExtensionHostKindPicker, - @IInstantiationService instantiationService: IInstantiationService, - @INotificationService notificationService: INotificationService, - @IBrowserWorkbenchEnvironmentService private readonly _browserEnvironmentService: IBrowserWorkbenchEnvironmentService, -@@ -68,21 +70,10 @@ export class ExtensionService extends AbstractExtensionService implements IExten - @IRemoteExplorerService private readonly _remoteExplorerService: IRemoteExplorerService, - @IDialogService dialogService: IDialogService, - ) { -- const extensionsProposedApi = instantiationService.createInstance(ExtensionsProposedApi); -- const extensionHostFactory = new BrowserExtensionHostFactory( -- extensionsProposedApi, -- () => this._scanWebExtensions(), -- () => this._getExtensionRegistrySnapshotWhenReady(), -- instantiationService, -- remoteAgentService, -- remoteAuthorityResolverService, -- extensionEnablementService, -- logService -- ); - super( - extensionsProposedApi, - extensionHostFactory, -- new BrowserExtensionHostKindPicker(logService), -+ extensionHostKindPicker, - instantiationService, - notificationService, - _browserEnvironmentService, -@@ -130,7 +121,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten - this._register(this._fileService.registerProvider(Schemas.https, provider)); - } - -- private async _scanWebExtensions(): Promise { -+ protected async _scanWebExtensions(): Promise { - const system: IExtensionDescription[] = [], user: IExtensionDescription[] = [], development: IExtensionDescription[] = []; - try { - await Promise.all([ -@@ -213,16 +204,16 @@ export class ExtensionService extends AbstractExtensionService implements IExten - } - } - --class BrowserExtensionHostFactory implements IExtensionHostFactory { -+export class BrowserExtensionHostFactory implements IExtensionHostFactory { - - constructor( - private readonly _extensionsProposedApi: ExtensionsProposedApi, - private readonly _scanWebExtensions: () => Promise, - private readonly _getExtensionRegistrySnapshotWhenReady: () => Promise, -- @IInstantiationService private readonly _instantiationService: IInstantiationService, -- @IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService, -- @IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, -- @IWorkbenchExtensionEnablementService private readonly _extensionEnablementService: IWorkbenchExtensionEnablementService, -+ @IInstantiationService protected readonly _instantiationService: IInstantiationService, -+ @IRemoteAgentService protected readonly _remoteAgentService: IRemoteAgentService, -+ @IRemoteAuthorityResolverService protected readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, -+ @IWorkbenchExtensionEnablementService protected readonly _extensionEnablementService: IWorkbenchExtensionEnablementService, - @ILogService private readonly _logService: ILogService, - ) { } - -@@ -249,7 +240,7 @@ class BrowserExtensionHostFactory implements IExtensionHostFactory { - } - } - -- private _createLocalExtensionHostDataProvider(runningLocations: ExtensionRunningLocationTracker, desiredRunningLocation: ExtensionRunningLocation, isInitialStart: boolean): IWebWorkerExtensionHostDataProvider { -+ protected _createLocalExtensionHostDataProvider(runningLocations: ExtensionRunningLocationTracker, desiredRunningLocation: ExtensionRunningLocation, isInitialStart: boolean): IWebWorkerExtensionHostDataProvider { - return { - getInitData: async (): Promise => { - if (isInitialStart) { -@@ -346,4 +337,71 @@ export class BrowserExtensionHostKindPicker implements IExtensionHostKindPicker - } - } - --registerSingleton(IExtensionService, ExtensionService, InstantiationType.Eager); -+export class BrowserExtensionService extends ExtensionService { -+ constructor( -+ @IInstantiationService instantiationService: IInstantiationService, -+ @INotificationService notificationService: INotificationService, -+ @IBrowserWorkbenchEnvironmentService browserEnvironmentService: IBrowserWorkbenchEnvironmentService, -+ @ITelemetryService telemetryService: ITelemetryService, -+ @IWorkbenchExtensionEnablementService extensionEnablementService: IWorkbenchExtensionEnablementService, -+ @IFileService fileService: IFileService, -+ @IProductService productService: IProductService, -+ @IWorkbenchExtensionManagementService extensionManagementService: IWorkbenchExtensionManagementService, -+ @IWorkspaceContextService contextService: IWorkspaceContextService, -+ @IConfigurationService configurationService: IConfigurationService, -+ @IExtensionManifestPropertiesService extensionManifestPropertiesService: IExtensionManifestPropertiesService, -+ @IWebExtensionsScannerService webExtensionsScannerService: IWebExtensionsScannerService, -+ @ILogService logService: ILogService, -+ @IRemoteAgentService remoteAgentService: IRemoteAgentService, -+ @IRemoteExtensionsScannerService remoteExtensionsScannerService: IRemoteExtensionsScannerService, -+ @ILifecycleService lifecycleService: ILifecycleService, -+ @IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService, -+ @IUserDataInitializationService userDataInitializationService: IUserDataInitializationService, -+ @IUserDataProfileService userDataProfileService: IUserDataProfileService, -+ @IWorkspaceTrustManagementService workspaceTrustManagementService: IWorkspaceTrustManagementService, -+ @IRemoteExplorerService remoteExplorerService: IRemoteExplorerService, -+ @IDialogService dialogService: IDialogService, -+ ) { -+ const extensionsProposedApi = instantiationService.createInstance(ExtensionsProposedApi); -+ const extensionHostFactory = new BrowserExtensionHostFactory( -+ extensionsProposedApi, -+ () => this._scanWebExtensions(), -+ () => this._getExtensionRegistrySnapshotWhenReady(), -+ instantiationService, -+ remoteAgentService, -+ remoteAuthorityResolverService, -+ extensionEnablementService, -+ logService -+ ); -+ super( -+ extensionsProposedApi, -+ extensionHostFactory, -+ new BrowserExtensionHostKindPicker(logService), -+ instantiationService, -+ notificationService, -+ browserEnvironmentService, -+ telemetryService, -+ extensionEnablementService, -+ fileService, -+ productService, -+ extensionManagementService, -+ contextService, -+ configurationService, -+ extensionManifestPropertiesService, -+ webExtensionsScannerService, -+ logService, -+ remoteAgentService, -+ remoteExtensionsScannerService, -+ lifecycleService, -+ remoteAuthorityResolverService, -+ userDataInitializationService, -+ userDataProfileService, -+ workspaceTrustManagementService, -+ remoteExplorerService, -+ dialogService -+ ); -+ } -+} -+ -+ -+registerSingleton(IExtensionService, BrowserExtensionService, InstantiationType.Eager); -diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts -index d019d14c4fb..78d4a00fa7f 100644 ---- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts -+++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts -@@ -98,7 +98,7 @@ type ExtensionUrlHandlerClassification = { - * - * It also makes sure the user confirms opening URLs directed towards extensions. - */ --class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { -+export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { - - readonly _serviceBrand: undefined; - -diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts -index b6d4f0f3831..7d462411a9c 100644 ---- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts -+++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts -@@ -76,7 +76,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost - this._extensionHostLogsLocation = joinPath(this._environmentService.extHostLogsPath, 'webWorker'); - } - -- private async _getWebWorkerExtensionHostIframeSrc(): Promise { -+ protected async _getWebWorkerExtensionHostIframeSrc(): Promise { - const suffixSearchParams = new URLSearchParams(); - if (this._environmentService.debugExtensionHost && this._environmentService.debugRenderer) { - suffixSearchParams.set('debugged', '1'); -@@ -111,8 +111,6 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost - res.searchParams.set('salt', stableOriginUUID); - return res.toString(); - } -- -- console.warn(`The web worker extension host is started in a same-origin iframe!`); - } - - const relativeExtensionHostIframeSrc = FileAccess.asBrowserUri(iframeModulePath); -diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts -index 2d93e41d0f0..0abfe0b61a3 100644 ---- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts -+++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts -@@ -94,9 +94,9 @@ export abstract class AbstractExtensionService extends Disposable implements IEx - private _resolveAuthorityAttempt: number = 0; - - constructor( -- private readonly _extensionsProposedApi: ExtensionsProposedApi, -- private readonly _extensionHostFactory: IExtensionHostFactory, -- private readonly _extensionHostKindPicker: IExtensionHostKindPicker, -+ protected readonly _extensionsProposedApi: ExtensionsProposedApi, -+ protected readonly _extensionHostFactory: IExtensionHostFactory, -+ protected readonly _extensionHostKindPicker: IExtensionHostKindPicker, - @IInstantiationService protected readonly _instantiationService: IInstantiationService, - @INotificationService protected readonly _notificationService: INotificationService, - @IWorkbenchEnvironmentService protected readonly _environmentService: IWorkbenchEnvironmentService, -@@ -211,7 +211,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx - - //#region deltaExtensions - -- private async _handleDeltaExtensions(item: DeltaExtensionsQueueItem): Promise { -+ protected async _handleDeltaExtensions(item: DeltaExtensionsQueueItem): Promise { - this._deltaExtensionsQueue.push(item); - if (this._inHandleDeltaExtensions) { - // Let the current item finish, the new one will be picked up -@@ -1193,7 +1193,7 @@ export interface IExtensionHostFactory { - createExtensionHost(runningLocations: ExtensionRunningLocationTracker, runningLocation: ExtensionRunningLocation, isInitialStart: boolean): IExtensionHost | null; - } - --class DeltaExtensionsQueueItem { -+export class DeltaExtensionsQueueItem { - constructor( - public readonly toAdd: IExtension[], - public readonly toRemove: string[] | IExtension[] -diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts -index 3ce96bba22a..d2067bf7445 100644 ---- a/src/vs/workbench/services/host/browser/browserHostService.ts -+++ b/src/vs/workbench/services/host/browser/browserHostService.ts -@@ -213,13 +213,18 @@ export class BrowserHostService extends Disposable implements IHostService { - const windowId = getWindowId(window); - const viewport = isIOS && window.visualViewport ? window.visualViewport /** Visual viewport */ : window /** Layout viewport */; - -+ const isFullScreen = () => { -+ const fullScreen = detectFullscreen(window); -+ return fullScreen !== null && !fullScreen.guess; -+ }; -+ - // Fullscreen (Browser) - for (const event of [EventType.FULLSCREEN_CHANGE, EventType.WK_FULLSCREEN_CHANGE]) { -- disposables.add(addDisposableListener(window.document, event, () => emitter.fire({ windowId, fullscreen: !!detectFullscreen(window) }))); -+ disposables.add(addDisposableListener(window.document, event, () => emitter.fire({ windowId, fullscreen: isFullScreen() }))); - } - - // Fullscreen (Native) -- disposables.add(addDisposableThrottledListener(viewport, EventType.RESIZE, () => emitter.fire({ windowId, fullscreen: !!detectFullscreen(window) }), undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */)); -+ disposables.add(addDisposableThrottledListener(viewport, EventType.RESIZE, () => emitter.fire({ windowId, fullscreen: isFullScreen() }), undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */)); - }, { window: mainWindow, disposables: this._store })); - - return emitter.event; -diff --git a/src/vs/workbench/services/keybinding/browser/keybindingService.ts b/src/vs/workbench/services/keybinding/browser/keybindingService.ts -index 708268ba3c3..956db0ac3bd 100644 ---- a/src/vs/workbench/services/keybinding/browser/keybindingService.ts -+++ b/src/vs/workbench/services/keybinding/browser/keybindingService.ts -@@ -423,15 +423,19 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { - return this.userKeybindings.keybindings.length; - } - -- private updateResolver(): void { -+ protected updateResolver(): void { - this._cachedResolver = null; - this._onDidUpdateKeybindings.fire(); - } - -+ protected getUserKeybindingItems() { -+ return this._resolveUserKeybindingItems(this.userKeybindings.keybindings, false); -+ } -+ - protected _getResolver(): KeybindingResolver { - if (!this._cachedResolver) { - const defaults = this._resolveKeybindingItems(KeybindingsRegistry.getDefaultKeybindings(), true); -- const overrides = this._resolveUserKeybindingItems(this.userKeybindings.keybindings, false); -+ const overrides = this.getUserKeybindingItems(); - this._cachedResolver = new KeybindingResolver(defaults, overrides, (str) => this._log(str)); - } - return this._cachedResolver; -diff --git a/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts b/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts -index bb50e96ff77..ab8d76f8903 100644 ---- a/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts -+++ b/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts -@@ -42,6 +42,7 @@ export class BrowserKeyboardMapperFactoryBase extends Disposable { - protected _keymapInfos: KeymapInfo[]; - protected _mru: KeymapInfo[]; - private _activeKeymapInfo: KeymapInfo | null; -+ private keyboardLayoutMapAllowed: boolean = (navigator as any).keyboard !== undefined; - - get activeKeymap(): KeymapInfo | null { - return this._activeKeymapInfo; -@@ -394,7 +395,7 @@ export class BrowserKeyboardMapperFactoryBase extends Disposable { - } - - private async _getBrowserKeyMapping(keyboardEvent?: IKeyboardEvent): Promise { -- if ((navigator as any).keyboard) { -+ if (this.keyboardLayoutMapAllowed) { - try { - return await (navigator as any).keyboard.getLayoutMap().then((e: any) => { - const ret: IKeyboardMapping = {}; -@@ -419,8 +420,10 @@ export class BrowserKeyboardMapperFactoryBase extends Disposable { - }); - } catch { - // getLayoutMap can throw if invoked from a nested browsing context -+ this.keyboardLayoutMapAllowed = false; - } -- } else if (keyboardEvent && !keyboardEvent.shiftKey && !keyboardEvent.altKey && !keyboardEvent.metaKey && !keyboardEvent.metaKey) { -+ } -+ if (keyboardEvent && !keyboardEvent.shiftKey && !keyboardEvent.altKey && !keyboardEvent.metaKey && !keyboardEvent.metaKey) { - const ret: IKeyboardMapping = {}; - const standardKeyboardEvent = keyboardEvent as StandardKeyboardEvent; - ret[standardKeyboardEvent.browserEvent.code] = { -diff --git a/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts b/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts -index f967fc38127..4da1da8f591 100644 ---- a/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts -+++ b/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts -@@ -3,14 +3,12 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import type { ModelOperations, ModelResult } from '@vscode/vscode-languagedetection'; -+import { ModelOperations, ModelResult } from '@vscode/vscode-languagedetection'; - import { StopWatch } from 'vs/base/common/stopwatch'; - import { IRequestHandler } from 'vs/base/common/worker/simpleWorker'; - import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker'; - import { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost'; - --type RegexpModel = { detect: (inp: string, langBiases: Record, supportedLangs?: string[]) => string | undefined }; -- - /** - * Called on the worker side - * @internal -@@ -28,9 +26,6 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker { - private static readonly positiveConfidenceCorrectionBucket2 = 0.025; - private static readonly negativeConfidenceCorrection = 0.5; - -- private _regexpModel: RegexpModel | undefined; -- private _regexpLoadFailed: boolean = false; -- - private _modelOperations: ModelOperations | undefined; - private _loadFailed: boolean = false; - -@@ -63,19 +58,8 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker { - return undefined; - }; - -- const historicalResolver = async () => this.runRegexpModel(documentTextSample, langBiases ?? {}, supportedLangs); -- -- if (preferHistory) { -- const history = await historicalResolver(); -- if (history) { return history; } -- const neural = await neuralResolver(); -- if (neural) { return neural; } -- } else { -- const neural = await neuralResolver(); -- if (neural) { return neural; } -- const history = await historicalResolver(); -- if (history) { return history; } -- } -+ const neural = await neuralResolver(); -+ if (neural) { return neural; } - - return undefined; - } -@@ -94,50 +78,11 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker { - return content; - } - -- private async getRegexpModel(): Promise { -- if (this._regexpLoadFailed) { -- return; -- } -- if (this._regexpModel) { -- return this._regexpModel; -- } -- const uri: string = await this._host.fhr('getRegexpModelUri', []); -- try { -- this._regexpModel = await import(uri) as RegexpModel; -- return this._regexpModel; -- } catch (e) { -- this._regexpLoadFailed = true; -- // console.warn('error loading language detection model', e); -- return; -- } -- } -- -- private async runRegexpModel(content: string, langBiases: Record, supportedLangs?: string[]): Promise { -- const regexpModel = await this.getRegexpModel(); -- if (!regexpModel) { return; } -- -- if (supportedLangs?.length) { -- // When using supportedLangs, normally computed biases are too extreme. Just use a "bitmask" of sorts. -- for (const lang of Object.keys(langBiases)) { -- if (supportedLangs.includes(lang)) { -- langBiases[lang] = 1; -- } else { -- langBiases[lang] = 0; -- } -- } -- } -- -- const detected = regexpModel.detect(content, langBiases, supportedLangs); -- return detected; -- } -- - private async getModelOperations(): Promise { - if (this._modelOperations) { - return this._modelOperations; - } - -- const uri: string = await this._host.fhr('getIndexJsUri', []); -- const { ModelOperations } = await import(uri) as typeof import('@vscode/vscode-languagedetection'); - this._modelOperations = new ModelOperations({ - modelJsonLoaderFunc: async () => { - const response = await fetch(await this._host.fhr('getModelJsonUri', [])); -diff --git a/src/vs/workbench/services/languageStatus/common/languageStatusService.ts b/src/vs/workbench/services/languageStatus/common/languageStatusService.ts -index e10d2a3ef1e..6dd88102a64 100644 ---- a/src/vs/workbench/services/languageStatus/common/languageStatusService.ts -+++ b/src/vs/workbench/services/languageStatus/common/languageStatusService.ts -@@ -47,7 +47,7 @@ export interface ILanguageStatusService { - } - - --class LanguageStatusServiceImpl implements ILanguageStatusService { -+export class LanguageStatusServiceImpl implements ILanguageStatusService { - - declare _serviceBrand: undefined; - -diff --git a/src/vs/workbench/services/outline/browser/outlineService.ts b/src/vs/workbench/services/outline/browser/outlineService.ts -index f4707432371..7c5cdde39cc 100644 ---- a/src/vs/workbench/services/outline/browser/outlineService.ts -+++ b/src/vs/workbench/services/outline/browser/outlineService.ts -@@ -11,7 +11,7 @@ import { IEditorPane } from 'vs/workbench/common/editor'; - import { IOutline, IOutlineCreator, IOutlineService, OutlineTarget } from 'vs/workbench/services/outline/browser/outline'; - import { Event, Emitter } from 'vs/base/common/event'; - --class OutlineService implements IOutlineService { -+export class OutlineService implements IOutlineService { - - declare _serviceBrand: undefined; - -diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts -index be889244846..875a9072cf0 100644 ---- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts -+++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts -@@ -139,7 +139,7 @@ export interface IRemoteExplorerService { - readonly namedProcesses: Map; - } - --class RemoteExplorerService implements IRemoteExplorerService { -+export class RemoteExplorerService implements IRemoteExplorerService { - public _serviceBrand: undefined; - private _targetType: string[] = []; - private readonly _onDidChangeTargetType: Emitter = new Emitter(); -diff --git a/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts b/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts -index a466cc1f3a1..09f6a40eb26 100644 ---- a/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts -+++ b/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts -@@ -16,7 +16,7 @@ import { ILogService } from 'vs/platform/log/common/log'; - import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; - import { IActiveLanguagePackService } from 'vs/workbench/services/localization/common/locale'; - --class RemoteExtensionsScannerService implements IRemoteExtensionsScannerService { -+export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerService { - - declare readonly _serviceBrand: undefined; - -diff --git a/src/vs/workbench/services/search/common/queryBuilder.ts b/src/vs/workbench/services/search/common/queryBuilder.ts -index 9124249957a..057b9a21ea2 100644 ---- a/src/vs/workbench/services/search/common/queryBuilder.ts -+++ b/src/vs/workbench/services/search/common/queryBuilder.ts -@@ -545,10 +545,10 @@ export class QueryBuilder { - folderName: includeFolderName ? folderName : undefined, - excludePattern: Object.keys(excludePattern).length > 0 ? excludePattern : undefined, - fileEncoding: folderConfig.files && folderConfig.files.encoding, -- disregardIgnoreFiles: typeof options.disregardIgnoreFiles === 'boolean' ? options.disregardIgnoreFiles : !folderConfig.search.useIgnoreFiles, -- disregardGlobalIgnoreFiles: typeof options.disregardGlobalIgnoreFiles === 'boolean' ? options.disregardGlobalIgnoreFiles : !folderConfig.search.useGlobalIgnoreFiles, -- disregardParentIgnoreFiles: typeof options.disregardParentIgnoreFiles === 'boolean' ? options.disregardParentIgnoreFiles : !folderConfig.search.useParentIgnoreFiles, -- ignoreSymlinks: typeof options.ignoreSymlinks === 'boolean' ? options.ignoreSymlinks : !folderConfig.search.followSymlinks, -+ disregardIgnoreFiles: typeof options.disregardIgnoreFiles === 'boolean' ? options.disregardIgnoreFiles : !folderConfig.search?.useIgnoreFiles, -+ disregardGlobalIgnoreFiles: typeof options.disregardGlobalIgnoreFiles === 'boolean' ? options.disregardGlobalIgnoreFiles : !folderConfig.search?.useGlobalIgnoreFiles, -+ disregardParentIgnoreFiles: typeof options.disregardParentIgnoreFiles === 'boolean' ? options.disregardParentIgnoreFiles : !folderConfig.search?.useParentIgnoreFiles, -+ ignoreSymlinks: typeof options.ignoreSymlinks === 'boolean' ? options.ignoreSymlinks : !folderConfig.search?.followSymlinks, - }; - } - } -diff --git a/src/vs/workbench/services/storage/browser/storageService.ts b/src/vs/workbench/services/storage/browser/storageService.ts -index a77c2db9446..2b9a8c19926 100644 ---- a/src/vs/workbench/services/storage/browser/storageService.ts -+++ b/src/vs/workbench/services/storage/browser/storageService.ts -@@ -34,6 +34,7 @@ export class BrowserStorageService extends AbstractStorageService { - - private workspaceStorage: IStorage | undefined; - private workspaceStorageDatabase: IIndexedDBStorageDatabase | undefined; -+ private readonly workspaceStorageDisposables = this._register(new DisposableStore()); - - get hasPendingUpdate(): boolean { - return Boolean( -@@ -44,7 +45,7 @@ export class BrowserStorageService extends AbstractStorageService { - } - - constructor( -- private readonly workspace: IAnyWorkspaceIdentifier, -+ private workspace: IAnyWorkspaceIdentifier, - private readonly userDataProfileService: IUserDataProfileService, - @ILogService private readonly logService: ILogService, - ) { -@@ -118,12 +119,15 @@ export class BrowserStorageService extends AbstractStorageService { - } - - private async createWorkspaceStorage(): Promise { -+ // First clear any previously associated disposables -+ this.workspaceStorageDisposables.clear(); -+ - const workspaceStorageIndexedDB = await IndexedDBStorageDatabase.createWorkspaceStorage(this.workspace.id, this.logService); - -- this.workspaceStorageDatabase = this._register(workspaceStorageIndexedDB); -- this.workspaceStorage = this._register(new Storage(this.workspaceStorageDatabase)); -+ this.workspaceStorageDatabase = this.workspaceStorageDisposables.add(workspaceStorageIndexedDB); -+ this.workspaceStorage = this.workspaceStorageDisposables.add(new Storage(this.workspaceStorageDatabase)); - -- this._register(this.workspaceStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.WORKSPACE, e))); -+ this.workspaceStorageDisposables.add(this.workspaceStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.WORKSPACE, e))); - - await this.workspaceStorage.init(); - -@@ -183,7 +187,18 @@ export class BrowserStorageService extends AbstractStorageService { - } - - protected async switchToWorkspace(toWorkspace: IAnyWorkspaceIdentifier, preserveData: boolean): Promise { -- throw new Error('Migrating storage is currently unsupported in Web'); -+ const oldWorkspaceStorage = assertIsDefined(this.workspaceStorage); -+ const oldItems = preserveData ? oldWorkspaceStorage.items : new Map(); -+ -+ // Close old workpace storage -+ await oldWorkspaceStorage.close(); -+ this.workspace = toWorkspace; -+ -+ // Create new workspace storage & init -+ await this.createWorkspaceStorage(); -+ -+ // Handle data switch and eventing -+ this.switchData(oldItems, assertIsDefined(this.workspaceStorage), StorageScope.WORKSPACE); - } - - protected override shouldFlushWhenIdle(): boolean { -diff --git a/src/vs/workbench/services/terminal/common/embedderTerminalService.ts b/src/vs/workbench/services/terminal/common/embedderTerminalService.ts -index 5e322af7a0f..07b4abdd636 100644 ---- a/src/vs/workbench/services/terminal/common/embedderTerminalService.ts -+++ b/src/vs/workbench/services/terminal/common/embedderTerminalService.ts -@@ -52,7 +52,7 @@ export interface IEmbedderTerminalPty { - // setDimensions?(dimensions: TerminalDimensions): void; - } - --class EmbedderTerminalService implements IEmbedderTerminalService { -+export class EmbedderTerminalService implements IEmbedderTerminalService { - declare _serviceBrand: undefined; - - private readonly _onDidCreateTerminal = new Emitter(); -diff --git a/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts b/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts -index 850b58e1e6c..2eb835fa2b6 100644 ---- a/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts -+++ b/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts -@@ -3,7 +3,6 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import { importAMDNodeModule } from 'vs/amdX'; - import { Disposable } from 'vs/base/common/lifecycle'; - import { IObservable, autorun, keepObserved, observableFromEvent } from 'vs/base/common/observable'; - import { countEOL } from 'vs/editor/common/core/eolCounter'; -@@ -17,7 +16,7 @@ import { ContiguousMultilineTokensBuilder } from 'vs/editor/common/tokens/contig - import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; - import { ArrayEdit, MonotonousIndexTransformer, SingleArrayEdit } from 'vs/workbench/services/textMate/browser/arrayOperation'; - import type { StateDeltas, TextMateTokenizationWorker } from 'vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker'; --import type { applyStateStackDiff, StateStack } from 'vscode-textmate'; -+import { StateStack, applyStateStackDiff, INITIAL } from 'vscode-textmate'; - - export class TextMateWorkerTokenizerController extends Disposable { - private static _id = 0; -@@ -178,7 +177,6 @@ export class TextMateWorkerTokenizerController extends Disposable { - ); - - if (!this._applyStateStackDiffFn || !this._initialState) { -- const { applyStateStackDiff, INITIAL } = await importAMDNodeModule('vscode-textmate', 'release/main.js'); - this._applyStateStackDiffFn = applyStateStackDiff; - this._initialState = INITIAL; - } -diff --git a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts -index 3974d642732..6e7de4d5d0d 100644 ---- a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts -+++ b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts -@@ -11,6 +11,8 @@ import { ICreateGrammarResult, TMGrammarFactory } from 'vs/workbench/services/te - import { IValidEmbeddedLanguagesMap, IValidGrammarDefinition, IValidTokenTypeMap } from 'vs/workbench/services/textMate/common/TMScopeRegistry'; - import type { IOnigLib, IRawTheme, StackDiff } from 'vscode-textmate'; - import { TextMateWorkerTokenizer } from './textMateWorkerTokenizer'; -+import * as vscodeTextmate from 'vscode-textmate'; -+import * as vscodeOniguruma from 'vscode-oniguruma'; - - /** - * Defines the worker entry point. Must be exported and named `create`. -@@ -78,9 +80,6 @@ export class TextMateTokenizationWorker { - } - - private async _loadTMGrammarFactory(grammarDefinitions: IValidGrammarDefinition[]): Promise { -- const uri = this._createData.textmateMainUri; -- const vscodeTextmate = await import(uri); -- const vscodeOniguruma = await import(this._createData.onigurumaMainUri); - const response = await fetch(this._createData.onigurumaWASMUri); - - // Using the response directly only works if the server sets the MIME type 'application/wasm'. -diff --git a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts -index bc98f7239ce..5937fa2286a 100644 ---- a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts -+++ b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts -@@ -3,7 +3,6 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import { importAMDNodeModule } from 'vs/amdX'; - import { RunOnceScheduler } from 'vs/base/common/async'; - import { observableValue } from 'vs/base/common/observable'; - import { setTimeout0 } from 'vs/base/common/platform'; -@@ -16,7 +15,7 @@ import { ContiguousMultilineTokensBuilder } from 'vs/editor/common/tokens/contig - import { LineTokens } from 'vs/editor/common/tokens/lineTokens'; - import { TextMateTokenizationSupport } from 'vs/workbench/services/textMate/browser/tokenizationSupport/textMateTokenizationSupport'; - import { TokenizationSupportWithLineLimit } from 'vs/workbench/services/textMate/browser/tokenizationSupport/tokenizationSupportWithLineLimit'; --import type { StackDiff, StateStack, diffStateStacksRefEq } from 'vscode-textmate'; -+import { StackDiff, StateStack, diffStateStacksRefEq } from 'vscode-textmate'; - import { ICreateGrammarResult } from 'vs/workbench/services/textMate/common/TMGrammarFactory'; - import { StateDeltas } from 'vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker'; - -@@ -113,7 +112,6 @@ export class TextMateWorkerTokenizer extends MirrorTextModel { - } - - if (!this._diffStateStacksRefEqFn) { -- const { diffStateStacksRefEq } = await importAMDNodeModule('vscode-textmate', 'release/main.js'); - this._diffStateStacksRefEqFn = diffStateStacksRefEq; - } - -diff --git a/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts b/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts -index 1ba671448d2..bec87c04f1e 100644 ---- a/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts -+++ b/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts -@@ -3,7 +3,6 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import { importAMDNodeModule } from 'vs/amdX'; - import * as dom from 'vs/base/browser/dom'; - import { equals as equalArray } from 'vs/base/common/arrays'; - import { Color } from 'vs/base/common/color'; -@@ -38,6 +37,8 @@ import { ITMSyntaxExtensionPoint, grammarsExtPoint } from 'vs/workbench/services - import { IValidEmbeddedLanguagesMap, IValidGrammarDefinition, IValidTokenTypeMap } from 'vs/workbench/services/textMate/common/TMScopeRegistry'; - import { ITextMateThemingRule, IWorkbenchColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; - import type { IGrammar, IOnigLib, IRawTheme } from 'vscode-textmate'; -+import * as vscodeTextmate from 'vscode-textmate'; -+import * as vscodeOniguruma from 'vscode-oniguruma'; - - export class TextMateTokenizationFeature extends Disposable implements ITextMateTokenizationService { - private static reportTokenizationTimeCounter = { sync: 0, async: 0 }; -@@ -245,7 +246,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate - return this._grammarFactory; - } - -- const [vscodeTextmate, vscodeOniguruma] = await Promise.all([importAMDNodeModule('vscode-textmate', 'release/main.js'), this._getVSCodeOniguruma()]); -+ const vscodeOniguruma = await this._getVSCodeOniguruma(); - const onigLib: Promise = Promise.resolve({ - createOnigScanner: (sources: string[]) => vscodeOniguruma.createOnigScanner(sources), - createOnigString: (str: string) => vscodeOniguruma.createOnigString(str) -@@ -356,7 +357,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate - private _getVSCodeOniguruma(): Promise { - if (!this._vscodeOniguruma) { - this._vscodeOniguruma = (async () => { -- const [vscodeOniguruma, wasm] = await Promise.all([importAMDNodeModule('vscode-oniguruma', 'release/main.js'), this._loadVSCodeOnigurumaWASM()]); -+ const wasm = await this._loadVSCodeOnigurumaWASM(); - await vscodeOniguruma.loadWASM({ - data: wasm, - print: (str: string) => { -diff --git a/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts b/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts -index a1a0779371e..18ca6d1b496 100644 ---- a/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts -+++ b/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts -@@ -3,7 +3,6 @@ - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - --import * as resources from 'vs/base/common/resources'; - import { URI } from 'vs/base/common/uri'; - import { LanguageId, StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; - -@@ -40,16 +39,6 @@ export class TMScopeRegistry { - } - - public register(def: IValidGrammarDefinition): void { -- if (this._scopeNameToLanguageRegistration[def.scopeName]) { -- const existingRegistration = this._scopeNameToLanguageRegistration[def.scopeName]; -- if (!resources.isEqual(existingRegistration.location, def.location)) { -- console.warn( -- `Overwriting grammar scope name to file mapping for scope ${def.scopeName}.\n` + -- `Old grammar file: ${existingRegistration.location.toString()}.\n` + -- `New grammar file: ${def.location.toString()}` -- ); -- } -- } - this._scopeNameToLanguageRegistration[def.scopeName] = def; - } - -diff --git a/src/vs/workbench/services/textfile/common/encoding.ts b/src/vs/workbench/services/textfile/common/encoding.ts -index ad67fb4f422..fadf86cece5 100644 ---- a/src/vs/workbench/services/textfile/common/encoding.ts -+++ b/src/vs/workbench/services/textfile/common/encoding.ts -@@ -5,7 +5,6 @@ - - import { Readable, ReadableStream, newWriteableStream, listenStream } from 'vs/base/common/stream'; - import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; --import { importAMDNodeModule } from 'vs/amdX'; - import { CancellationTokenSource } from 'vs/base/common/cancellation'; - - export const UTF8 = 'utf8'; -@@ -80,7 +79,7 @@ class DecoderStream implements IDecoderStream { - static async create(encoding: string): Promise { - let decoder: IDecoderStream | undefined = undefined; - if (encoding !== UTF8) { -- const iconv = await importAMDNodeModule('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js'); -+ const iconv = await import('@vscode/iconv-lite-umd'); - decoder = iconv.getDecoder(toNodeEncoding(encoding)); - } else { - const utf8TextDecoder = new TextDecoder(); -@@ -213,7 +212,7 @@ export function toDecodeStream(source: VSBufferReadableStream, options: IDecodeS - } - - export async function toEncodeReadable(readable: Readable, encoding: string, options?: { addBOM?: boolean }): Promise { -- const iconv = await importAMDNodeModule('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js'); -+ const iconv = await import('@vscode/iconv-lite-umd'); - const encoder = iconv.getEncoder(toNodeEncoding(encoding), options); - - let bytesWritten = false; -@@ -262,7 +261,7 @@ export async function toEncodeReadable(readable: Readable, encoding: str - } - - export async function encodingExists(encoding: string): Promise { -- const iconv = await importAMDNodeModule('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js'); -+ const iconv = await import('@vscode/iconv-lite-umd'); - - return iconv.encodingExists(toNodeEncoding(encoding)); - } -@@ -318,7 +317,7 @@ const IGNORE_ENCODINGS = ['ascii', 'utf-16', 'utf-32']; - * Guesses the encoding from buffer. - */ - async function guessEncodingByBuffer(buffer: VSBuffer): Promise { -- const jschardet = await importAMDNodeModule('jschardet', 'dist/jschardet.min.js'); -+ const jschardet = await import('jschardet'); - - // ensure to limit buffer for guessing due to https://github.com/aadsm/jschardet/issues/53 - const limitedBuffer = buffer.slice(0, AUTO_ENCODING_GUESS_MAX_BYTES); -diff --git a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts -index 9a7bf4aa503..235e0ed2948 100644 ---- a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts -+++ b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts -@@ -186,7 +186,7 @@ class ColorDataRenderer extends Disposable implements IExtensionFeatureTableRend - color.description, - toColor(color.defaults.dark) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.dark}\``), - toColor(color.defaults.light) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.light}\``), -- toColor(color.defaults.highContrast) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.highContrast}\``), -+ toColor(color.defaults.highContrast!) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.highContrast}\``), - ]; - }); - -diff --git a/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts b/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts -index 80f5ee077cb..49abd845677 100644 ---- a/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts -+++ b/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts -@@ -69,6 +69,7 @@ const tokenModifierExtPoint = ExtensionsRegistry.registerExtensionPoint; - } - --class RemoteUserDataProfilesService extends Disposable implements IRemoteUserDataProfilesService { -+export class RemoteUserDataProfilesService extends Disposable implements IRemoteUserDataProfilesService { - - readonly _serviceBrand: undefined; - -diff --git a/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts b/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts -index 45329df40c4..84119b7c042 100644 ---- a/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts -+++ b/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts -@@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; - import { ITextModelService } from 'vs/editor/common/services/resolverService'; - import { ITextResourcePropertiesService, ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; - --class UserDataSyncUtilService implements IUserDataSyncUtilService { -+export class UserDataSyncUtilService implements IUserDataSyncUtilService { - - declare readonly _serviceBrand: undefined; - -diff --git a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts -index 21312c7e76c..1f89122e0df 100644 ---- a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts -+++ b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts -@@ -14,7 +14,7 @@ import { ConfigurationScope, IConfigurationRegistry, Extensions as Configuration - import { Registry } from 'vs/platform/registry/common/platform'; - import { ICommandService } from 'vs/platform/commands/common/commands'; - import { distinct, firstOrDefault } from 'vs/base/common/arrays'; --import { basename, isEqual, isEqualAuthority, joinPath, removeTrailingPathSeparator } from 'vs/base/common/resources'; -+import { basename, isEqual, joinPath, removeTrailingPathSeparator } from 'vs/base/common/resources'; - import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; - import { IFileService } from 'vs/platform/files/common/files'; - import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -@@ -169,11 +169,6 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi - - private async doAddFolders(foldersToAdd: IWorkspaceFolderCreationData[], index?: number, donotNotifyError: boolean = false): Promise { - const state = this.contextService.getWorkbenchState(); -- const remoteAuthority = this.environmentService.remoteAuthority; -- if (remoteAuthority) { -- // https://github.com/microsoft/vscode/issues/94191 -- foldersToAdd = foldersToAdd.filter(folder => folder.uri.scheme !== Schemas.file && (folder.uri.scheme !== Schemas.vscodeRemote || isEqualAuthority(folder.uri.authority, remoteAuthority))); -- } - - // If we are in no-workspace or single-folder workspace, adding folders has to - // enter a workspace. diff --git a/src/service-override/views.ts b/src/service-override/views.ts index 7c11a88c..29a5f06f 100644 --- a/src/service-override/views.ts +++ b/src/service-override/views.ts @@ -604,6 +604,21 @@ onRenderWorkbench(async (accessor) => { } } + // If we opened a view in the sidebar, stop any restore there + if (locationsRestored[ViewContainerLocation.Sidebar] != null) { + initialLayoutState.views.containerToRestore.sideBar = locationsRestored[ViewContainerLocation.Sidebar].id + } + + // If we opened a view in the panel, stop any restore there + if (locationsRestored[ViewContainerLocation.Panel] != null) { + initialLayoutState.views.containerToRestore.panel = locationsRestored[ViewContainerLocation.Panel].id + } + + // If we opened a view in the auxiliary bar, stop any restore there + if (locationsRestored[ViewContainerLocation.AuxiliaryBar] != null) { + initialLayoutState.views.containerToRestore.auxiliaryBar = locationsRestored[ViewContainerLocation.AuxiliaryBar].id + } + mark('code/didOpenDefaultViews') } })() diff --git a/vscode-paches/0001-fix-allow-importing-vscode-oniguruma.patch b/vscode-paches/0001-fix-allow-importing-vscode-oniguruma.patch new file mode 100644 index 00000000..a7c0b99d --- /dev/null +++ b/vscode-paches/0001-fix-allow-importing-vscode-oniguruma.patch @@ -0,0 +1,24 @@ +From c816fc894631d4e10c09c613e4875d0da97100d7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:40:57 +0100 +Subject: [PATCH 01/58] fix: allow importing vscode-oniguruma + +--- + .eslintrc.json | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/.eslintrc.json b/.eslintrc.json +index 0922babfe92..59769eeda54 100644 +--- a/.eslintrc.json ++++ b/.eslintrc.json +@@ -671,6 +671,7 @@ + "v8-inspect-profiler", + "vscode-regexpp", + "vscode-textmate", ++ "vscode-oniguruma", + "worker_threads", + "@xterm/addon-canvas", + "@xterm/addon-image", +-- +2.34.1 + diff --git a/vscode-paches/0002-fix-fix-editor-api-types.patch b/vscode-paches/0002-fix-fix-editor-api-types.patch new file mode 100644 index 00000000..4d5943a4 --- /dev/null +++ b/vscode-paches/0002-fix-fix-editor-api-types.patch @@ -0,0 +1,34 @@ +From e72487c8dc1c7ded54f3753976c89d2e41ca5872 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:41:55 +0100 +Subject: [PATCH 02/58] fix: fix editor api types + +--- + build/gulpfile.editor.js | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js +index 22b70a953df..e781d39d9e2 100644 +--- a/build/gulpfile.editor.js ++++ b/build/gulpfile.editor.js +@@ -277,7 +277,16 @@ function toExternalDTS(contents) { + } + + if (line.indexOf('declare let MonacoEnvironment') === 0) { +- lines[i] = `declare global {\n let MonacoEnvironment: Environment | undefined;\n}`; ++ lines[i] = [ ++ 'declare global {', ++ ' let MonacoEnvironment: Environment | undefined;', ++ '', ++ ' interface Window {', ++ ' MonacoEnvironment?: Environment | undefined;', ++ ' }', ++ '}', ++ '' ++ ].join('\n'); + } + + if (line.indexOf('\tMonacoEnvironment?') === 0) { +-- +2.34.1 + diff --git a/vscode-paches/0003-fix-fix-some-build-process-edge-cases.patch b/vscode-paches/0003-fix-fix-some-build-process-edge-cases.patch new file mode 100644 index 00000000..0f1389c2 --- /dev/null +++ b/vscode-paches/0003-fix-fix-some-build-process-edge-cases.patch @@ -0,0 +1,63 @@ +From 8108407d456dba533370212e90adfd19ece98319 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:42:35 +0100 +Subject: [PATCH 03/58] fix: fix some build process edge cases + +--- + build/lib/standalone.js | 7 +++++++ + build/lib/standalone.ts | 7 +++++++ + 2 files changed, 14 insertions(+) + +diff --git a/build/lib/standalone.js b/build/lib/standalone.js +index 4ddf88ed223..d24023726cd 100644 +--- a/build/lib/standalone.js ++++ b/build/lib/standalone.js +@@ -150,6 +150,9 @@ function createESMSourcesAndResources2(options) { + const info = ts.preProcessFile(fileContents); + for (let i = info.importedFiles.length - 1; i >= 0; i--) { + const importedFilename = info.importedFiles[i].fileName; ++ if (!importedFilename.startsWith('vs/')) { ++ continue; ++ } + const pos = info.importedFiles[i].pos; + const end = info.importedFiles[i].end; + let importedFilepath; +@@ -172,6 +175,10 @@ function createESMSourcesAndResources2(options) { + else { + relativePath = path.relative(path.dirname(file), importedFilepath); + } ++ if (relativePath.endsWith('..')) { ++ // When a folder have the same name as a file ++ relativePath = relativePath + '/../' + path.basename(importedFilepath); ++ } + relativePath = relativePath.replace(/\\/g, '/'); + if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { + relativePath = './' + relativePath; +diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts +index 775a1be5996..ce8435bd920 100644 +--- a/build/lib/standalone.ts ++++ b/build/lib/standalone.ts +@@ -180,6 +180,9 @@ export function createESMSourcesAndResources2(options: IOptions2): void { + + for (let i = info.importedFiles.length - 1; i >= 0; i--) { + const importedFilename = info.importedFiles[i].fileName; ++ if (!importedFilename.startsWith('vs/')) { ++ continue; ++ } + const pos = info.importedFiles[i].pos; + const end = info.importedFiles[i].end; + +@@ -201,6 +204,10 @@ export function createESMSourcesAndResources2(options: IOptions2): void { + } else { + relativePath = path.relative(path.dirname(file), importedFilepath); + } ++ if (relativePath.endsWith('..')) { ++ // When a folder have the same name as a file ++ relativePath = relativePath + '/../' + path.basename(importedFilepath); ++ } + relativePath = relativePath.replace(/\\/g, '/'); + if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { + relativePath = './' + relativePath; +-- +2.34.1 + diff --git a/vscode-paches/0004-cleanup-remove-amd-build-to-speed-up-editor-build.patch b/vscode-paches/0004-cleanup-remove-amd-build-to-speed-up-editor-build.patch new file mode 100644 index 00000000..379bd6c8 --- /dev/null +++ b/vscode-paches/0004-cleanup-remove-amd-build-to-speed-up-editor-build.patch @@ -0,0 +1,38 @@ +From 6f0b37c46903402a1df195467990e443fd1a7f0c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:44:07 +0100 +Subject: [PATCH 04/58] cleanup: remove amd build to speed up editor build + +--- + build/gulpfile.editor.js | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js +index e781d39d9e2..4c92c45941a 100644 +--- a/build/gulpfile.editor.js ++++ b/build/gulpfile.editor.js +@@ -413,17 +413,10 @@ gulp.task('editor-distro', + util.rimraf('out-editor-min') + ), + extractEditorSrcTask, +- task.parallel( +- task.series( +- compileEditorAMDTask, +- optimizeEditorAMDTask, +- minifyEditorAMDTask +- ), +- task.series( +- createESMSourcesAndResourcesTask, +- compileEditorESMTask, +- appendJSToESMImportsTask +- ) ++ task.series( ++ createESMSourcesAndResourcesTask, ++ compileEditorESMTask, ++ appendJSToESMImportsTask + ), + finalEditorResourcesTask + ) +-- +2.34.1 + diff --git a/vscode-paches/0005-feat-output-es2020.patch b/vscode-paches/0005-feat-output-es2020.patch new file mode 100644 index 00000000..c927fdce --- /dev/null +++ b/vscode-paches/0005-feat-output-es2020.patch @@ -0,0 +1,39 @@ +From 24c535ceef82265bcaf1a5d901b98f0c3e717d8f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:44:35 +0100 +Subject: [PATCH 05/58] feat: output es2020 + +--- + build/lib/standalone.js | 2 +- + build/lib/standalone.ts | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/build/lib/standalone.js b/build/lib/standalone.js +index d24023726cd..2ffc91efc9c 100644 +--- a/build/lib/standalone.js ++++ b/build/lib/standalone.js +@@ -134,7 +134,7 @@ function createESMSourcesAndResources2(options) { + } + if (file === 'tsconfig.json') { + const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); +- tsConfig.compilerOptions.module = 'es6'; ++ tsConfig.compilerOptions.module = 'es2020'; + tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/'); + write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); + continue; +diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts +index ce8435bd920..90517a9236f 100644 +--- a/build/lib/standalone.ts ++++ b/build/lib/standalone.ts +@@ -160,7 +160,7 @@ export function createESMSourcesAndResources2(options: IOptions2): void { + + if (file === 'tsconfig.json') { + const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); +- tsConfig.compilerOptions.module = 'es6'; ++ tsConfig.compilerOptions.module = 'es2020'; + tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/'); + write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); + continue; +-- +2.34.1 + diff --git a/vscode-paches/0006-feat-add-a-way-to-register-a-locale-with-translation.patch b/vscode-paches/0006-feat-add-a-way-to-register-a-locale-with-translation.patch new file mode 100644 index 00000000..0587d3c8 --- /dev/null +++ b/vscode-paches/0006-feat-add-a-way-to-register-a-locale-with-translation.patch @@ -0,0 +1,100 @@ +From 7da0ea2de48343828487f09296ec309d4f2816cd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:45:29 +0100 +Subject: [PATCH 06/58] feat: add a way to register a locale with translations + +--- + build/lib/standalone.js | 7 +++++++ + build/lib/standalone.ts | 8 ++++++++ + src/vs/nls.ts | 31 ++++++++++++++++++++++++++++++- + 3 files changed, 45 insertions(+), 1 deletion(-) + +diff --git a/build/lib/standalone.js b/build/lib/standalone.js +index 2ffc91efc9c..ddb16108fda 100644 +--- a/build/lib/standalone.js ++++ b/build/lib/standalone.js +@@ -190,6 +190,13 @@ function createESMSourcesAndResources2(options) { + fileContents = fileContents.replace(/import ([a-zA-Z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) { + return `import * as ${m1} from ${m2};`; + }); ++ if (!file.includes('vs/nls')) { ++ fileContents = fileContents.replace(/\b(localize2?)\(/g, function (_, name) { ++ return `${name}WithPath('${file.slice(0, -3)}', `; ++ }); ++ } ++ fileContents = fileContents.replace(/import { (localize2?) }/g, 'import { $1WithPath }'); ++ fileContents = fileContents.replace(/import { localize, localize2 }/g, 'import { localizeWithPath, localize2WithPath }'); + write(getDestAbsoluteFilePath(file), fileContents); + continue; + } +diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts +index 90517a9236f..224f376d4bf 100644 +--- a/build/lib/standalone.ts ++++ b/build/lib/standalone.ts +@@ -223,6 +223,14 @@ export function createESMSourcesAndResources2(options: IOptions2): void { + return `import * as ${m1} from ${m2};`; + }); + ++ if (!file.includes('vs/nls')) { ++ fileContents = fileContents.replace(/\b(localize2?)\(/g, function (_, name) { ++ return `${name}WithPath('${file.slice(0, -3)}', `; ++ }); ++ } ++ fileContents = fileContents.replace(/import { (localize2?) }/g, 'import { $1WithPath }'); ++ fileContents = fileContents.replace(/import { localize, localize2 }/g, 'import { localizeWithPath, localize2WithPath }'); ++ + write(getDestAbsoluteFilePath(file), fileContents); + continue; + } +diff --git a/src/vs/nls.ts b/src/vs/nls.ts +index 233840e65ab..ff3661e3472 100644 +--- a/src/vs/nls.ts ++++ b/src/vs/nls.ts +@@ -164,6 +164,35 @@ export function localize(data: ILocalizeInfo | string, message: string, ...args: + return _format(message, args); + } + ++let locale: string | undefined = undefined; ++let translations: Record> = {}; ++ ++export function setLocale(_locale: string, _translations: Record>) { ++ locale = _locale; ++ translations = _translations; ++} ++ ++/** ++ * @skipMangle ++ */ ++export function localizeWithPath(path: string, data: ILocalizeInfo | string, defaultMessage: string, ...args: (string | number | boolean | undefined | null)[]): string { ++ const key = typeof data === 'object' ? data.key : data; ++ const message = (translations[path] ?? {})[key] ?? defaultMessage; ++ return _format(message, args); ++} ++ ++/** ++ * @skipMangle ++ */ ++export function localize2WithPath(path: string, data: ILocalizeInfo | string, defaultMessage: string, ...args: (string | number | boolean | undefined | null)[]): ILocalizedString { ++ const key = typeof data === 'object' ? data.key : data; ++ const message = (translations[path] ?? {})[key] ?? defaultMessage; ++ return { ++ value: _format(message, args), ++ original: _format(defaultMessage, args) ++ }; ++} ++ + /** + * Marks a string to be localized. Returns an {@linkcode ILocalizedString} + * which contains the localized string and the original string. +@@ -217,7 +246,7 @@ export function getConfiguredDefaultLocale(stringFromLocalizeCall: string): stri + export function getConfiguredDefaultLocale(_: string): string | undefined { + // This returns undefined because this implementation isn't used and is overwritten by the loader + // when loaded. +- return undefined; ++ return locale; + } + + /** +-- +2.34.1 + diff --git a/vscode-paches/0007-fixup-feat-output-es2020.patch b/vscode-paches/0007-fixup-feat-output-es2020.patch new file mode 100644 index 00000000..f04ab63f --- /dev/null +++ b/vscode-paches/0007-fixup-feat-output-es2020.patch @@ -0,0 +1,44 @@ +From e5ef89fb7b3c753e413263dff99555c82c5b4518 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:45:53 +0100 +Subject: [PATCH 07/58] fixup! feat: output es2020 + +--- + src/tsconfig.base.json | 3 ++- + src/tsconfig.monaco.json | 4 ++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/tsconfig.base.json b/src/tsconfig.base.json +index c0a2e174591..1d80c22afa3 100644 +--- a/src/tsconfig.base.json ++++ b/src/tsconfig.base.json +@@ -1,6 +1,7 @@ + { + "compilerOptions": { +- "module": "amd", ++ "esModuleInterop": true, ++ "module": "ES2020", + "moduleResolution": "node", + "experimentalDecorators": true, + "noImplicitReturns": true, +diff --git a/src/tsconfig.monaco.json b/src/tsconfig.monaco.json +index 988f0485713..c73b524ea2a 100644 +--- a/src/tsconfig.monaco.json ++++ b/src/tsconfig.monaco.json +@@ -7,11 +7,11 @@ + "wicg-file-system-access" + ], + "paths": {}, +- "module": "amd", ++ "module": "es2020", + "moduleResolution": "classic", + "removeComments": false, + "preserveConstEnums": true, +- "target": "es2018", ++ "target": "es2020", + "sourceMap": false, + "declaration": true + }, +-- +2.34.1 + diff --git a/vscode-paches/0008-fix-markdown-do-not-encode-i10l-location.patch b/vscode-paches/0008-fix-markdown-do-not-encode-i10l-location.patch new file mode 100644 index 00000000..6955dd14 --- /dev/null +++ b/vscode-paches/0008-fix-markdown-do-not-encode-i10l-location.patch @@ -0,0 +1,25 @@ +From 7e53575e8b8dc013d91047bdcdde8bf0d75ca1e2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:46:45 +0100 +Subject: [PATCH 08/58] fix(markdown): do not encode i10l location + +--- + extensions/markdown-language-features/src/extension.browser.ts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/markdown-language-features/src/extension.browser.ts b/extensions/markdown-language-features/src/extension.browser.ts +index 30639672490..2095905a4d8 100644 +--- a/extensions/markdown-language-features/src/extension.browser.ts ++++ b/extensions/markdown-language-features/src/extension.browser.ts +@@ -30,7 +30,7 @@ function startServer(context: vscode.ExtensionContext, parser: IMdParser): Promi + const serverMain = vscode.Uri.joinPath(context.extensionUri, 'server/dist/browser/workerMain.js'); + + const worker = new Worker(serverMain.toString()); +- worker.postMessage({ i10lLocation: vscode.l10n.uri?.toString() ?? '' }); ++ worker.postMessage({ i10lLocation: vscode.l10n.uri?.toString(true) ?? '' }); + + return startClient((id: string, name: string, clientOptions: LanguageClientOptions) => { + return new LanguageClient(id, name, clientOptions, worker); +-- +2.34.1 + diff --git a/vscode-paches/0009-fix-typescript-handle-trailing-slash.patch b/vscode-paches/0009-fix-typescript-handle-trailing-slash.patch new file mode 100644 index 00000000..4ae3ddfe --- /dev/null +++ b/vscode-paches/0009-fix-typescript-handle-trailing-slash.patch @@ -0,0 +1,25 @@ +From 37cf174a96d33cf100d966a527d2e958077e3c14 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:47:24 +0100 +Subject: [PATCH 09/58] fix(typescript): handle trailing slash + +--- + extensions/typescript-language-features/web/src/pathMapper.ts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/typescript-language-features/web/src/pathMapper.ts b/extensions/typescript-language-features/web/src/pathMapper.ts +index e92548950fc..b24ba5155d3 100644 +--- a/extensions/typescript-language-features/web/src/pathMapper.ts ++++ b/extensions/typescript-language-features/web/src/pathMapper.ts +@@ -20,7 +20,7 @@ export class PathMapper { + return URI.from({ + scheme: this.extensionUri.scheme, + authority: this.extensionUri.authority, +- path: this.extensionUri.path + '/dist/browser/typescript/' + filepath.slice(1) ++ path: this.extensionUri.path.replace(/\/$/, '') + '/dist/browser/typescript/' + filepath.slice(1) + }); + } + +-- +2.34.1 + diff --git a/vscode-paches/0010-fix-typescript-missing-default-value.patch b/vscode-paches/0010-fix-typescript-missing-default-value.patch new file mode 100644 index 00000000..bb056030 --- /dev/null +++ b/vscode-paches/0010-fix-typescript-missing-default-value.patch @@ -0,0 +1,25 @@ +From 02b40ff300716dfb3ab800ac10621194d5c5d433 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:48:25 +0100 +Subject: [PATCH 10/58] fix(typescript): missing default value + +--- + extensions/typescript-language-features/web/src/pathMapper.ts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/typescript-language-features/web/src/pathMapper.ts b/extensions/typescript-language-features/web/src/pathMapper.ts +index b24ba5155d3..a0c2c248f96 100644 +--- a/extensions/typescript-language-features/web/src/pathMapper.ts ++++ b/extensions/typescript-language-features/web/src/pathMapper.ts +@@ -76,7 +76,7 @@ export function fromResource(extensionUri: URI, uri: URI) { + && uri.path.endsWith('.d.ts')) { + return uri.path; + } +- return `/${uri.scheme}/${uri.authority}${uri.path}`; ++ return `/${uri.scheme}/${uri.authority || 'ts-nul-authority'}${uri.path}`; + } + + export function looksLikeLibDtsPath(filepath: string) { +-- +2.34.1 + diff --git a/vscode-paches/0011-fix-typescript-handle-missing-case.patch b/vscode-paches/0011-fix-typescript-handle-missing-case.patch new file mode 100644 index 00000000..e39c202e --- /dev/null +++ b/vscode-paches/0011-fix-typescript-handle-missing-case.patch @@ -0,0 +1,27 @@ +From 2e0616e25fab6513e9da87c47ea6dbad6b2e0d02 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 16:50:57 +0100 +Subject: [PATCH 11/58] fix(typescript): handle missing case + +--- + .../web/src/typingsInstaller/typingsInstaller.ts | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts b/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts +index 7c40993d6df..950ed338c30 100644 +--- a/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts ++++ b/extensions/typescript-language-features/web/src/typingsInstaller/typingsInstaller.ts +@@ -66,7 +66,9 @@ export class WebTypingsInstallerClient implements ts.server.ITypingsInstaller { + case 'action::packageInstalled': + case 'action::invalidate': + case 'action::set': +- this.projectService!.updateTypingsForProject(response); ++ // missing case leads to error ++ case 'action::watchTypingLocations': ++ this.projectService!.updateTypingsForProject(response as ts.server.PackageInstalledResponse | ts.server.SetTypings | ts.server.InvalidateCachedTypings); + break; + case 'event::beginInstallTypes': + case 'event::endInstallTypes': +-- +2.34.1 + diff --git a/vscode-paches/0012-feat-add-static-asset-url-mechanism.patch b/vscode-paches/0012-feat-add-static-asset-url-mechanism.patch new file mode 100644 index 00000000..58d69b7e --- /dev/null +++ b/vscode-paches/0012-feat-add-static-asset-url-mechanism.patch @@ -0,0 +1,404 @@ +From a44d5eef6d3fea3ad4c01b4f0a9963420961c7c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:11:14 +0100 +Subject: [PATCH 12/58] feat: add static asset url mechanism + +--- + src/vs/base/common/network.ts | 45 +++- + .../api/browser/mainThreadExtensionService.ts | 7 + + .../workbench/api/common/extensionHostMain.ts | 5 + + .../api/worker/extensionHostWorker.ts | 219 +++++++++++++----- + 4 files changed, 217 insertions(+), 59 deletions(-) + +diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts +index 974d0c21743..aae916fa686 100644 +--- a/src/vs/base/common/network.ts ++++ b/src/vs/base/common/network.ts +@@ -4,6 +4,8 @@ + *--------------------------------------------------------------------------------------------*/ + + import * as errors from 'vs/base/common/errors'; ++import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; ++import { ResourceMap } from 'vs/base/common/map'; + import * as platform from 'vs/base/common/platform'; + import { equalsIgnoreCase, startsWithIgnoreCase } from 'vs/base/common/strings'; + import { URI } from 'vs/base/common/uri'; +@@ -223,6 +225,30 @@ export const VSCODE_AUTHORITY = 'vscode-app'; + class FileAccessImpl { + + private static readonly FALLBACK_AUTHORITY = VSCODE_AUTHORITY; ++ private staticBrowserUris = new ResourceMap(); ++ private appResourcePathUrls = new Map string)>(); ++ ++ private moduleContentProvider = new Map Promise>(); ++ ++ public registerModuleContentProvider(moduleId: string, contentLoader: () => Promise) { ++ this.moduleContentProvider.set(moduleId, contentLoader); ++ } ++ ++ public toModuleContent(moduleId: string): Promise { ++ return this.moduleContentProvider.get(moduleId)!(); ++ } ++ ++ public registerAppResourcePathUrl(moduleId: string, url: string | (() => string)): void { ++ this.appResourcePathUrls.set(moduleId, url); ++ } ++ ++ private toUrl(moduleId: string): string { ++ let url = this.appResourcePathUrls.get(moduleId); ++ if (typeof url === 'function') { ++ url = url(); ++ } ++ return new URL(url ?? moduleId, globalThis.location?.href ?? import.meta.url).toString(); ++ } + + /** + * Returns a URI to use in contexts where the browser is responsible +@@ -231,7 +257,7 @@ class FileAccessImpl { + * **Note:** use `dom.ts#asCSSUrl` whenever the URL is to be used in CSS context. + */ + asBrowserUri(resourcePath: AppResourcePath | ''): URI { +- const uri = this.toUri(resourcePath, require); ++ const uri = this.toUri(resourcePath, { toUrl: this.toUrl.bind(this) }); + return this.uriToBrowserUri(uri); + } + +@@ -270,7 +296,7 @@ class FileAccessImpl { + }); + } + +- return uri; ++ return this.staticBrowserUris.get(uri) ?? uri; + } + + /** +@@ -278,7 +304,7 @@ class FileAccessImpl { + * is responsible for loading. + */ + asFileUri(resourcePath: AppResourcePath | ''): URI { +- const uri = this.toUri(resourcePath, require); ++ const uri = this.toUri(resourcePath, { toUrl: this.toUrl.bind(this) }); + return this.uriToFileUri(uri); + } + +@@ -310,6 +336,19 @@ class FileAccessImpl { + + return URI.parse(moduleIdToUrl.toUrl(uriOrModule)); + } ++ ++ registerStaticBrowserUri(uri: URI, browserUri: URI): IDisposable { ++ this.staticBrowserUris.set(uri, browserUri); ++ return toDisposable(() => { ++ if (this.staticBrowserUris.get(uri) === browserUri) { ++ this.staticBrowserUris.delete(uri); ++ } ++ }); ++ } ++ ++ getRegisteredBrowserUris(): IterableIterator { ++ return this.staticBrowserUris.keys(); ++ } + } + + export const FileAccess = new FileAccessImpl(); +diff --git a/src/vs/workbench/api/browser/mainThreadExtensionService.ts b/src/vs/workbench/api/browser/mainThreadExtensionService.ts +index 6732d38f5e6..72abfc8af21 100644 +--- a/src/vs/workbench/api/browser/mainThreadExtensionService.ts ++++ b/src/vs/workbench/api/browser/mainThreadExtensionService.ts +@@ -193,6 +193,13 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha + async $asBrowserUri(uri: UriComponents): Promise { + return FileAccess.uriToBrowserUri(URI.revive(uri)); + } ++ ++ async $getAllStaticBrowserUris(): Promise<[UriComponents, UriComponents][]> { ++ return Array.from(FileAccess.getRegisteredBrowserUris(), uri => [ ++ uri, ++ FileAccess.uriToBrowserUri(uri) ++ ]); ++ } + } + + class ExtensionHostProxy implements IExtensionHostProxy { +diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts +index 2bd275cbc21..f1c84b938a2 100644 +--- a/src/vs/workbench/api/common/extensionHostMain.ts ++++ b/src/vs/workbench/api/common/extensionHostMain.ts +@@ -189,6 +189,11 @@ export class ExtensionHostMain { + return URI.revive(await mainThreadExtensionsProxy.$asBrowserUri(uri)); + } + ++ async getAllStaticBrowserUris(): Promise<[URI, URI][]> { ++ const mainThreadExtensionsProxy = this._rpcProtocol.getProxy(MainContext.MainThreadExtensionService); ++ return (await mainThreadExtensionsProxy.$getAllStaticBrowserUris()).map(([from, to]) => [URI.revive(from), URI.revive(to)]); ++ } ++ + terminate(reason: string): void { + this._extensionService.terminate(reason); + } +diff --git a/src/vs/workbench/api/worker/extensionHostWorker.ts b/src/vs/workbench/api/worker/extensionHostWorker.ts +index 86136a080e6..8a2608599ee 100644 +--- a/src/vs/workbench/api/worker/extensionHostWorker.ts ++++ b/src/vs/workbench/api/worker/extensionHostWorker.ts +@@ -15,7 +15,6 @@ import * as performance from 'vs/base/common/performance'; + + import 'vs/workbench/api/common/extHost.common.services'; + import 'vs/workbench/api/worker/extHost.worker.services'; +-import { FileAccess } from 'vs/base/common/network'; + import { URI } from 'vs/base/common/uri'; + + //#region --- Define, capture, and override some globals +@@ -35,6 +34,7 @@ declare namespace self { + let importScripts: any; + let fetch: _Fetch; + let XMLHttpRequest: any; ++ let importExt: any; + } + + const nativeClose = self.close.bind(self); +@@ -47,7 +47,7 @@ function shouldTransformUri(uri: string): boolean { + // In principle, we could convert any URI, but we have concerns + // that parsing https URIs might end up decoding escape characters + // and result in an unintended transformation +- return /^(file|vscode-remote):/i.test(uri); ++ return /^(file|extension-file|vscode-remote):/i.test(uri); + } + + const nativeFetch = fetch.bind(self); +@@ -89,66 +89,172 @@ self.addEventListener = () => console.trace(`'addEventListener' has been blocked + (self)['webkitResolveLocalFileSystemSyncURL'] = undefined; + (self)['webkitResolveLocalFileSystemURL'] = undefined; + +-if ((self).Worker) { +- +- // make sure new Worker(...) always uses blob: (to maintain current origin) +- const _Worker = (self).Worker; +- Worker = function (stringUrl: string | URL, options?: WorkerOptions) { +- if (/^file:/i.test(stringUrl.toString())) { +- stringUrl = FileAccess.uriToBrowserUri(URI.parse(stringUrl.toString())).toString(true); +- } else if (/^vscode-remote:/i.test(stringUrl.toString())) { +- // Supporting transformation of vscode-remote URIs requires an async call to the main thread, +- // but we cannot do this call from within the embedded Worker, and the only way out would be +- // to use templating instead of a function in the web api (`resourceUriProvider`) +- throw new Error(`Creating workers from remote extensions is currently not supported.`); +- } ++function patchWorker(asBrowserUri: (uri: URI) => Promise, getAllStaticBrowserUris: () => Promise<[URI, URI][]>) { ++ if ((self).Worker) { ++ ++ // make sure new Worker(...) always uses blob: (to maintain current origin) ++ const _Worker = (self).Worker; ++ Worker = function (stringUrl: string | URL, options?: WorkerOptions) { ++ if (/^vscode-remote:/i.test(stringUrl.toString())) { ++ // Supporting transformation of vscode-remote URIs requires an async call to the main thread, ++ // but we cannot do this call from within the embedded Worker, and the only way out would be ++ // to use templating instead of a function in the web api (`resourceUriProvider`) ++ throw new Error(`Creating workers from remote extensions is currently not supported.`); ++ } + +- // IMPORTANT: bootstrapFn is stringified and injected as worker blob-url. Because of that it CANNOT +- // have dependencies on other functions or variables. Only constant values are supported. Due to +- // that logic of FileAccess.asBrowserUri had to be copied, see `asWorkerBrowserUrl` (below). +- const bootstrapFnSource = (function bootstrapFn(workerUrl: string) { +- function asWorkerBrowserUrl(url: string | URL | TrustedScriptURL): any { +- if (typeof url === 'string' || url instanceof URL) { +- return String(url).replace(/^file:\/\//i, 'vscode-file://vscode-app'); +- } +- return url; ++ async function getWorkerUri(workerUri: URI): Promise { ++ const [browserUrl, staticBrowserUrls] = await Promise.all([ ++ asBrowserUri(workerUri).then(uri => uri.toString(true)), ++ getAllStaticBrowserUris().then(bindings => Object.fromEntries(bindings.map(([from, to]) => [from.toString(true), to.toString(true)]))) ++ ]); ++ ++ // IMPORTANT: bootstrapFn is stringified and injected as worker blob-url. Because of that it CANNOT ++ // have dependencies on other functions or variables. Only constant values are supported. Due to ++ // that logic of FileAccess.asBrowserUri had to be copied, see `asWorkerBrowserUrl` (below). ++ const bootstrapFnSource = (function bootstrapFn(workerUrl: string, staticBrowserUrls: Record) { ++ function asWorkerBrowserUrl(url: string | URL | TrustedScriptURL): any { ++ if (typeof url === 'string' || url instanceof URL) { ++ url = String(url).replace(/^file:\/\//i, 'vscode-file://vscode-app'); ++ return staticBrowserUrls[url] ?? url; ++ } ++ return url; ++ } ++ ++ const nativeFetch = fetch.bind(self); ++ self.fetch = function (input, init) { ++ if (input instanceof Request) { ++ // Request object - massage not supported ++ return nativeFetch(input, init); ++ } ++ return nativeFetch(asWorkerBrowserUrl(input), init); ++ }; ++ self.XMLHttpRequest = class extends XMLHttpRequest { ++ private notFound = false; ++ override open(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null): void { ++ const transformedUrl = asWorkerBrowserUrl(url); ++ this.notFound = transformedUrl.startsWith('extension-file:'); ++ return super.open(method, transformedUrl, async ?? true, username, password); ++ } ++ override send(body?: Document | XMLHttpRequestBodyInit | null | undefined): void { ++ if (this.notFound) { ++ return; ++ } ++ super.send(body); ++ } ++ override get status() { ++ return this.notFound ? 404 : super.status; ++ } ++ }; ++ const nativeImportScripts = importScripts.bind(self); ++ self.importScripts = (...urls: string[]) => { ++ nativeImportScripts(...urls.map(asWorkerBrowserUrl)); ++ }; ++ ++ self.importExt = (url: string) => { ++ // prevent bundler from trying to transform dynamic import ++ return new Function('url', 'return import(url)')(asWorkerBrowserUrl(url)); ++ }; ++ ++ nativeImportScripts(workerUrl); ++ }).toString(); ++ ++ const js = `(${bootstrapFnSource}('${browserUrl}', ${JSON.stringify(staticBrowserUrls)}))`; ++ ++ const blob = new Blob([js], { type: 'application/javascript' }); ++ return URL.createObjectURL(blob); + } + +- const nativeFetch = fetch.bind(self); +- self.fetch = function (input, init) { +- if (input instanceof Request) { +- // Request object - massage not supported +- return nativeFetch(input, init); ++ options = options || {}; ++ options.name = `${name} -> ${options.name || path.basename(stringUrl.toString())}`; ++ ++ class ExtensionWorker implements Worker { ++ private workerPromise: Promise; ++ constructor(scriptURL: string | URL, options?: WorkerOptions) { ++ this.workerPromise = getWorkerUri(URI.parse(scriptURL instanceof URL ? scriptURL.toString() : scriptURL)).then(url => { ++ return new _Worker(url, options); ++ }); + } +- return nativeFetch(asWorkerBrowserUrl(input), init); +- }; +- self.XMLHttpRequest = class extends XMLHttpRequest { +- override open(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null): void { +- return super.open(method, asWorkerBrowserUrl(url), async ?? true, username, password); ++ ++ private _onmessage: Worker['onmessage'] = null; ++ set onmessage(cb: Worker['onmessage']) { ++ this._onmessage = cb; ++ this.workerPromise.then(worker => { ++ worker.onmessage = cb; ++ }, console.error); + } +- }; +- const nativeImportScripts = importScripts.bind(self); +- self.importScripts = (...urls: string[]) => { +- nativeImportScripts(...urls.map(asWorkerBrowserUrl)); +- }; +- +- nativeImportScripts(workerUrl); +- }).toString(); +- +- const js = `(${bootstrapFnSource}('${stringUrl}'))`; +- options = options || {}; +- options.name = `${name} -> ${options.name || path.basename(stringUrl.toString())}`; +- const blob = new Blob([js], { type: 'application/javascript' }); +- const blobUrl = URL.createObjectURL(blob); +- return new _Worker(blobUrl, options); +- }; + +-} else { +- (self).Worker = class extends NestedWorker { +- constructor(stringOrUrl: string | URL, options?: WorkerOptions) { +- super(nativePostMessage, stringOrUrl, { name: path.basename(stringOrUrl.toString()), ...options }); +- } +- }; ++ get onmessage(): Worker['onmessage'] { ++ return this._onmessage; ++ } ++ ++ private _onmessageerror: Worker['onmessageerror'] = null; ++ set onmessageerror(cb: Worker['onmessageerror']) { ++ this._onmessageerror = cb; ++ this.workerPromise.then(worker => { ++ worker.onmessageerror = cb; ++ }, console.error); ++ } ++ ++ get onmessageerror(): Worker['onmessageerror'] { ++ return this._onmessageerror; ++ } ++ ++ private _onerror: Worker['onerror'] = null; ++ set onerror(cb: Worker['onerror']) { ++ this._onerror = cb; ++ this.workerPromise.then(worker => { ++ worker.onerror = cb; ++ }, console.error); ++ } ++ ++ get onerror(): Worker['onerror'] { ++ return this._onerror; ++ } ++ ++ // eslint-disable-next-line @typescript-eslint/no-explicit-any ++ postMessage(message: unknown, options?: any): void { ++ this.workerPromise.then(worker => { ++ worker.postMessage(message, options); ++ }, console.error); ++ } ++ ++ terminate(): void { ++ this.workerPromise.then(worker => { ++ worker.terminate(); ++ }, console.error); ++ } ++ ++ // eslint-disable-next-line @typescript-eslint/no-explicit-any ++ addEventListener(type: any, listener: any, options?: any): void { ++ this.workerPromise.then(worker => { ++ worker.addEventListener(type, listener, options); ++ }, console.error); ++ } ++ ++ // eslint-disable-next-line @typescript-eslint/no-explicit-any ++ removeEventListener(type: any, listener: any, options?: any): void { ++ this.workerPromise.then(worker => { ++ worker.removeEventListener(type, listener, options); ++ }, console.error); ++ } ++ ++ dispatchEvent(event: Event): boolean { ++ this.workerPromise.then(worker => { ++ worker.dispatchEvent(event); ++ }, console.error); ++ return false; ++ } ++ } ++ return new ExtensionWorker(stringUrl, options); ++ }; ++ ++ } else { ++ (self).Worker = class extends NestedWorker { ++ constructor(stringOrUrl: string | URL, options?: WorkerOptions) { ++ super(nativePostMessage, stringOrUrl, { name: path.basename(stringOrUrl.toString()), ...options }); ++ } ++ }; ++ } + } + + //#endregion --- +@@ -255,6 +361,7 @@ export function create(): { onmessage: (message: any) => void } { + ); + + patchFetching(uri => extHostMain.asBrowserUri(uri)); ++ patchWorker(uri => extHostMain.asBrowserUri(uri), () => extHostMain.getAllStaticBrowserUris()); + + onTerminate = (reason: string) => extHostMain.terminate(reason); + }); +-- +2.34.1 + diff --git a/vscode-paches/0013-fix-remove-import-in-ESM.patch b/vscode-paches/0013-fix-remove-import-in-ESM.patch new file mode 100644 index 00000000..dd1e27e5 --- /dev/null +++ b/vscode-paches/0013-fix-remove-import-in-ESM.patch @@ -0,0 +1,26 @@ +From 4de935e674716989bd97c33c694fe8d316e5ffa2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:11:37 +0100 +Subject: [PATCH 13/58] fix: remove import in ESM + +--- + src/vs/base/browser/defaultWorkerFactory.ts | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/vs/base/browser/defaultWorkerFactory.ts b/src/vs/base/browser/defaultWorkerFactory.ts +index 71391b063f3..7878de1cbfa 100644 +--- a/src/vs/base/browser/defaultWorkerFactory.ts ++++ b/src/vs/base/browser/defaultWorkerFactory.ts +@@ -5,7 +5,9 @@ + + import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes'; + import { onUnexpectedError } from 'vs/base/common/errors'; ++// ESM-comment-begin + import { COI } from 'vs/base/common/network'; ++// ESM-comment-end + import { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker'; + import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; + +-- +2.34.1 + diff --git a/vscode-paches/0014-fix-remove-ttf-url-search-parameter-breaking-import.patch b/vscode-paches/0014-fix-remove-ttf-url-search-parameter-breaking-import.patch new file mode 100644 index 00000000..ef170971 --- /dev/null +++ b/vscode-paches/0014-fix-remove-ttf-url-search-parameter-breaking-import.patch @@ -0,0 +1,25 @@ +From 724683e02b1201c946c5f50622cb665ffad1f328 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:12:08 +0100 +Subject: [PATCH 14/58] fix: remove ttf url search parameter breaking import + +--- + src/vs/base/browser/ui/codicons/codicon/codicon.css | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.css b/src/vs/base/browser/ui/codicons/codicon/codicon.css +index 02154e77b68..d7f257db934 100644 +--- a/src/vs/base/browser/ui/codicons/codicon/codicon.css ++++ b/src/vs/base/browser/ui/codicons/codicon/codicon.css +@@ -6,7 +6,7 @@ + @font-face { + font-family: "codicon"; + font-display: block; +- src: url("./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6") format("truetype"); ++ src: url("./codicon.ttf") format("truetype"); + } + + .codicon[class*='codicon-'] { +-- +2.34.1 + diff --git a/vscode-paches/0015-fix-ESM-version-of-performance.patch b/vscode-paches/0015-fix-ESM-version-of-performance.patch new file mode 100644 index 00000000..128f9fde --- /dev/null +++ b/vscode-paches/0015-fix-ESM-version-of-performance.patch @@ -0,0 +1,53 @@ +From e0dae16b2ad90e9ae4a31a6f5e57e326e528773e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:12:32 +0100 +Subject: [PATCH 15/58] fix: ESM version of performance + +--- + src/vs/base/common/performance.js | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js +index aff4d0734de..ea43e4a2fcc 100644 +--- a/src/vs/base/common/performance.js ++++ b/src/vs/base/common/performance.js +@@ -6,7 +6,7 @@ + 'use strict'; + + //@ts-check +- ++// ESM-comment-begin + (function () { + + /** +@@ -123,3 +123,27 @@ + } + + })(); ++// ESM-comment-end ++ ++// ESM-uncomment-begin ++// export const mark = (name) => { ++// performance.mark(name); ++// }; ++ ++// export const getMarks = () => { ++// let timeOrigin = performance.timeOrigin; ++// if (typeof timeOrigin !== 'number') { ++// // safari: there is no timerOrigin but in renderers there is the timing-property ++// // see https://bugs.webkit.org/show_bug.cgi?id=174862 ++// timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart; ++// } ++// const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }]; ++// for (const entry of performance.getEntriesByType('mark')) { ++// result.push({ ++// name: entry.name, ++// startTime: Math.round(timeOrigin + entry.startTime) ++// }); ++// } ++// return result; ++// }; ++// ESM-uncomment-end +-- +2.34.1 + diff --git a/vscode-paches/0016-fix-apply-style-only-on-standalone-editors.patch b/vscode-paches/0016-fix-apply-style-only-on-standalone-editors.patch new file mode 100644 index 00000000..9f1d810b --- /dev/null +++ b/vscode-paches/0016-fix-apply-style-only-on-standalone-editors.patch @@ -0,0 +1,218 @@ +From 26a6c2cdc69046c58736a021a9052d5a34c65480 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:13:49 +0100 +Subject: [PATCH 16/58] fix: apply style only on standalone editors + +--- + .../browser/config/editorConfiguration.ts | 12 ++++++-- + .../editor/browser/widget/codeEditorWidget.ts | 12 ++++++-- + .../widget/diffEditor/diffEditorWidget.ts | 8 ++++++ + .../standalone/browser/standalone-tokens.css | 28 +++++++++---------- + .../browser/standaloneCodeEditor.ts | 4 +-- + 5 files changed, 42 insertions(+), 22 deletions(-) + +diff --git a/src/vs/editor/browser/config/editorConfiguration.ts b/src/vs/editor/browser/config/editorConfiguration.ts +index 06e8339cbc7..799c2f81cd0 100644 +--- a/src/vs/editor/browser/config/editorConfiguration.ts ++++ b/src/vs/editor/browser/config/editorConfiguration.ts +@@ -43,6 +43,7 @@ export class EditorConfiguration extends Disposable implements IEditorConfigurat + public readonly onDidChangeFast: Event = this._onDidChangeFast.event; + + public readonly isSimpleWidget: boolean; ++ public readonly isStandaloneEditor: boolean; + private readonly _containerObserver: ElementSizeObserver; + + private _isDominatedByLongLines: boolean = false; +@@ -68,12 +69,14 @@ export class EditorConfiguration extends Disposable implements IEditorConfigurat + + constructor( + isSimpleWidget: boolean, ++ isStandaloneEditor: boolean, + options: Readonly, + container: HTMLElement | null, + @IAccessibilityService private readonly _accessibilityService: IAccessibilityService + ) { + super(); + this.isSimpleWidget = isSimpleWidget; ++ this.isStandaloneEditor = isStandaloneEditor; + this._containerObserver = this._register(new ElementSizeObserver(container, options.dimension)); + this._targetWindowId = getWindow(container).vscodeWindowId; + +@@ -130,7 +133,7 @@ export class EditorConfiguration extends Disposable implements IEditorConfigurat + + protected _readEnvConfiguration(): IEnvConfiguration { + return { +- extraEditorClassName: getExtraEditorClassName(), ++ extraEditorClassName: getExtraEditorClassName(this.isStandaloneEditor), + outerWidth: this._containerObserver.getWidth(), + outerHeight: this._containerObserver.getHeight(), + emptySelectionClipboard: browser.isWebKit || browser.isFirefox, +@@ -218,7 +221,7 @@ function digitCount(n: number): number { + return r ? r : 1; + } + +-function getExtraEditorClassName(): string { ++function getExtraEditorClassName(isStandaloneEditor: boolean): string { + let extra = ''; + if (!browser.isSafari && !browser.isWebkitWebView) { + // Use user-select: none in all browsers except Safari and native macOS WebView +@@ -232,6 +235,9 @@ function getExtraEditorClassName(): string { + if (platform.isMacintosh) { + extra += 'mac '; + } ++ if (isStandaloneEditor) { ++ extra += 'standalone '; ++ } + return extra; + } + +@@ -273,7 +279,7 @@ export class ComputedEditorOptions implements IComputedEditorOptions { + } + } + +-class EditorOptionsUtil { ++export class EditorOptionsUtil { + + public static validateOptions(options: IEditorOptions): ValidatedEditorOptions { + const result = new ValidatedEditorOptions(); +diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts +index 5466f913d24..d8dfad03a43 100644 +--- a/src/vs/editor/browser/widget/codeEditorWidget.ts ++++ b/src/vs/editor/browser/widget/codeEditorWidget.ts +@@ -70,6 +70,12 @@ export interface ICodeEditorWidgetOptions { + */ + isSimpleWidget?: boolean; + ++ /** ++ * Is this a standalone editor ++ * Defaults to false. ++ */ ++ isStandaloneEditor?: boolean; ++ + /** + * Contributions to instantiate. + * When provided, only the contributions included will be instantiated. +@@ -300,7 +306,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE + this._decorationTypeSubtypes = {}; + this._telemetryData = codeEditorWidgetOptions.telemetryData; + +- this._configuration = this._register(this._createConfiguration(codeEditorWidgetOptions.isSimpleWidget || false, options, accessibilityService)); ++ this._configuration = this._register(this._createConfiguration(codeEditorWidgetOptions.isSimpleWidget || false, codeEditorWidgetOptions.isStandaloneEditor || false, options, accessibilityService)); + this._register(this._configuration.onDidChange((e) => { + this._onDidChangeConfiguration.fire(e); + +@@ -408,8 +414,8 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE + this._modelData?.view.writeScreenReaderContent(reason); + } + +- protected _createConfiguration(isSimpleWidget: boolean, options: Readonly, accessibilityService: IAccessibilityService): EditorConfiguration { +- return new EditorConfiguration(isSimpleWidget, options, this._domElement, accessibilityService); ++ protected _createConfiguration(isSimpleWidget: boolean, isStandaloneEditor: boolean, options: Readonly, accessibilityService: IAccessibilityService): EditorConfiguration { ++ return new EditorConfiguration(isSimpleWidget, isStandaloneEditor, options, this._domElement, accessibilityService); + } + + public getId(): string { +diff --git a/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts +index 6b57de66397..67837f9885e 100644 +--- a/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts ++++ b/src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts +@@ -49,6 +49,12 @@ import { RevertButtonsFeature } from 'vs/editor/browser/widget/diffEditor/featur + export interface IDiffCodeEditorWidgetOptions { + originalEditor?: ICodeEditorWidgetOptions; + modifiedEditor?: ICodeEditorWidgetOptions; ++ ++ /** ++ * Is this a standalone editor ++ * Defaults to false. ++ */ ++ isStandaloneEditor?: boolean; + } + + export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor { +@@ -105,6 +111,8 @@ export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor { + + this._contextKeyService.createKey('isInDiffEditor', true); + ++ this.elements.root.classList.toggle('standalone', codeEditorWidgetOptions.isStandaloneEditor || false); ++ + this._domElement.appendChild(this.elements.root); + this._register(toDisposable(() => this._domElement.removeChild(this.elements.root))); + +diff --git a/src/vs/editor/standalone/browser/standalone-tokens.css b/src/vs/editor/standalone/browser/standalone-tokens.css +index 1fc85078f9e..c74aca00541 100644 +--- a/src/vs/editor/standalone/browser/standalone-tokens.css ++++ b/src/vs/editor/standalone/browser/standalone-tokens.css +@@ -5,7 +5,7 @@ + + + /* Default standalone editor fonts */ +-.monaco-editor { ++.monaco-editor.standalone { + font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", system-ui, "Ubuntu", "Droid Sans", sans-serif; + --monaco-monospace-font: "SF Mono", Monaco, Menlo, Consolas, "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace; + } +@@ -14,9 +14,9 @@ + stroke-width: 1.2px; + } + +-.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, +-.monaco-editor.hc-black .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, +-.monaco-editor.hc-light .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label { ++.monaco-editor.standalone.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, ++.monaco-editor.standalone.hc-black .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label, ++.monaco-editor.standalone.hc-light .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label { + stroke-width: 1.2px; + } + +@@ -37,16 +37,16 @@ + clip-path: inset(50%); + } + +-.monaco-editor, .monaco-diff-editor .synthetic-focus, +-.monaco-editor, .monaco-diff-editor [tabindex="0"]:focus, +-.monaco-editor, .monaco-diff-editor [tabindex="-1"]:focus, +-.monaco-editor, .monaco-diff-editor button:focus, +-.monaco-editor, .monaco-diff-editor input[type=button]:focus, +-.monaco-editor, .monaco-diff-editor input[type=checkbox]:focus, +-.monaco-editor, .monaco-diff-editor input[type=search]:focus, +-.monaco-editor, .monaco-diff-editor input[type=text]:focus, +-.monaco-editor, .monaco-diff-editor select:focus, +-.monaco-editor, .monaco-diff-editor textarea:focus { ++.monaco-editor.standalone, .monaco-diff-editor.standalone .synthetic-focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone [tabindex="0"]:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone [tabindex="-1"]:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone button:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=button]:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=checkbox]:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=search]:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone input[type=text]:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone select:focus, ++.monaco-editor.standalone, .monaco-diff-editor.standalone textarea:focus { + outline-width: 1px; + outline-style: solid; + outline-offset: -1px; +diff --git a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +index 479bb75745c..f5b5da97a2c 100644 +--- a/src/vs/editor/standalone/browser/standaloneCodeEditor.ts ++++ b/src/vs/editor/standalone/browser/standaloneCodeEditor.ts +@@ -282,7 +282,7 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon + const options = { ..._options }; + options.ariaLabel = options.ariaLabel || StandaloneCodeEditorNLS.editorViewAccessibleLabel; + options.ariaLabel = options.ariaLabel + ';' + (StandaloneCodeEditorNLS.accessibilityHelpMessage); +- super(domElement, options, {}, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService); ++ super(domElement, options, { isStandaloneEditor: true }, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService, languageConfigurationService, languageFeaturesService); + + if (keybindingService instanceof StandaloneKeybindingService) { + this._standaloneKeybindingService = keybindingService; +@@ -518,7 +518,7 @@ export class StandaloneDiffEditor2 extends DiffEditorWidget implements IStandalo + super( + domElement, + options, +- {}, ++ { isStandaloneEditor: true }, + contextKeyService, + instantiationService, + codeEditorService, +-- +2.34.1 + diff --git a/vscode-paches/0017-fix-use-existing-method.patch b/vscode-paches/0017-fix-use-existing-method.patch new file mode 100644 index 00000000..2be299c0 --- /dev/null +++ b/vscode-paches/0017-fix-use-existing-method.patch @@ -0,0 +1,25 @@ +From 2a22436234fd47d83e798fcd5e0f683dda6f8c81 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:14:41 +0100 +Subject: [PATCH 17/58] fix: use existing method + +--- + src/vs/editor/standalone/browser/standaloneServices.ts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts +index 351f85537d8..cf0f43c7d48 100644 +--- a/src/vs/editor/standalone/browser/standaloneServices.ts ++++ b/src/vs/editor/standalone/browser/standaloneServices.ts +@@ -554,7 +554,7 @@ export class StandaloneKeybindingService extends AbstractKeybindingService { + // This might be a removal keybinding item in user settings => accept it + result[resultLen++] = new ResolvedKeybindingItem(undefined, item.command, item.commandArgs, when, isDefault, null, false); + } else { +- const resolvedKeybindings = USLayoutResolvedKeybinding.resolveKeybinding(keybinding, OS); ++ const resolvedKeybindings = this.resolveKeybinding(keybinding); + for (const resolvedKeybinding of resolvedKeybindings) { + result[resultLen++] = new ResolvedKeybindingItem(resolvedKeybinding, item.command, item.commandArgs, when, isDefault, null, false); + } +-- +2.34.1 + diff --git a/vscode-paches/0018-refactor-split-code.patch b/vscode-paches/0018-refactor-split-code.patch new file mode 100644 index 00000000..a12f55f5 --- /dev/null +++ b/vscode-paches/0018-refactor-split-code.patch @@ -0,0 +1,38 @@ +From 5e3e2281266924398533c620c26b01db4627e245 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:14:56 +0100 +Subject: [PATCH 18/58] refactor: split code + +--- + src/vs/editor/standalone/browser/standaloneServices.ts | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts +index cf0f43c7d48..a2565626513 100644 +--- a/src/vs/editor/standalone/browser/standaloneServices.ts ++++ b/src/vs/editor/standalone/browser/standaloneServices.ts +@@ -525,15 +525,19 @@ export class StandaloneKeybindingService extends AbstractKeybindingService { + }); + } + +- private updateResolver(): void { ++ protected updateResolver(): void { + this._cachedResolver = null; + this._onDidUpdateKeybindings.fire(); + } + ++ protected getUserKeybindingItems() { ++ return this._toNormalizedKeybindingItems(this._dynamicKeybindings, false); ++ } ++ + protected _getResolver(): KeybindingResolver { + if (!this._cachedResolver) { + const defaults = this._toNormalizedKeybindingItems(KeybindingsRegistry.getDefaultKeybindings(), true); +- const overrides = this._toNormalizedKeybindingItems(this._dynamicKeybindings, false); ++ const overrides = this.getUserKeybindingItems(); + this._cachedResolver = new KeybindingResolver(defaults, overrides, (str) => this._log(str)); + } + return this._cachedResolver; +-- +2.34.1 + diff --git a/vscode-paches/0019-cleanup-remove-code-already-done-in-EditorFeaturesIn.patch b/vscode-paches/0019-cleanup-remove-code-already-done-in-EditorFeaturesIn.patch new file mode 100644 index 00000000..dc1157d0 --- /dev/null +++ b/vscode-paches/0019-cleanup-remove-code-already-done-in-EditorFeaturesIn.patch @@ -0,0 +1,43 @@ +From 5ef17e9f56cf78f1417c66bbad8b6291908b050c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:15:40 +0100 +Subject: [PATCH 19/58] cleanup: remove code already done in + EditorFeaturesInstantiator + +--- + .../editor/standalone/browser/standaloneServices.ts | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts +index a2565626513..d6995d24729 100644 +--- a/src/vs/editor/standalone/browser/standaloneServices.ts ++++ b/src/vs/editor/standalone/browser/standaloneServices.ts +@@ -90,8 +90,6 @@ import { DefaultConfiguration } from 'vs/platform/configuration/common/configura + import { WorkspaceEdit } from 'vs/editor/common/languages'; + import { AccessibilitySignal, IAccessibilitySignalService, Sound } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService'; + import { LogService } from 'vs/platform/log/common/logService'; +-import { getEditorFeatures } from 'vs/editor/common/editorFeatures'; +-import { onUnexpectedError } from 'vs/base/common/errors'; + import { ExtensionKind, IEnvironmentService, IExtensionHostDebugParams } from 'vs/platform/environment/common/environment'; + import { mainWindow } from 'vs/base/browser/window'; + +@@ -1187,16 +1185,6 @@ export module StandaloneServices { + } + } + +- // Instantiate all editor features +- const editorFeatures = getEditorFeatures(); +- for (const feature of editorFeatures) { +- try { +- instantiationService.createInstance(feature); +- } catch (err) { +- onUnexpectedError(err); +- } +- } +- + onDidInitialize.fire(); + + return instantiationService; +-- +2.34.1 + diff --git a/vscode-paches/0020-fixup-fix-apply-style-only-on-standalone-editors.patch b/vscode-paches/0020-fixup-fix-apply-style-only-on-standalone-editors.patch new file mode 100644 index 00000000..9076a2a3 --- /dev/null +++ b/vscode-paches/0020-fixup-fix-apply-style-only-on-standalone-editors.patch @@ -0,0 +1,39 @@ +From 39d109f59aa34ce663a369f38a7e51a8ea82765a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:16:02 +0100 +Subject: [PATCH 20/58] fixup! fix: apply style only on standalone editors + +--- + src/vs/editor/test/browser/config/testConfiguration.ts | 2 +- + src/vs/editor/test/browser/testCodeEditor.ts | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/vs/editor/test/browser/config/testConfiguration.ts b/src/vs/editor/test/browser/config/testConfiguration.ts +index b5d42908ded..3815f8fb823 100644 +--- a/src/vs/editor/test/browser/config/testConfiguration.ts ++++ b/src/vs/editor/test/browser/config/testConfiguration.ts +@@ -13,7 +13,7 @@ import { TestAccessibilityService } from 'vs/platform/accessibility/test/common/ + export class TestConfiguration extends EditorConfiguration { + + constructor(opts: Readonly) { +- super(false, opts, null, new TestAccessibilityService()); ++ super(false, false, opts, null, new TestAccessibilityService()); + } + + protected override _readEnvConfiguration(): IEnvConfiguration { +diff --git a/src/vs/editor/test/browser/testCodeEditor.ts b/src/vs/editor/test/browser/testCodeEditor.ts +index b29e05c8053..f941b3a248f 100644 +--- a/src/vs/editor/test/browser/testCodeEditor.ts ++++ b/src/vs/editor/test/browser/testCodeEditor.ts +@@ -68,7 +68,7 @@ export interface ITestCodeEditor extends IActiveCodeEditor { + export class TestCodeEditor extends CodeEditorWidget implements ICodeEditor { + + //#region testing overrides +- protected override _createConfiguration(isSimpleWidget: boolean, options: Readonly): EditorConfiguration { ++ protected override _createConfiguration(isSimpleWidget: boolean, isStandaloneEditor: boolean, options: Readonly): EditorConfiguration { + return new TestConfiguration(options); + } + protected override _createView(viewModel: ViewModel): [View, boolean] { +-- +2.34.1 + diff --git a/vscode-paches/0021-fix-replace-amd-imports-by-regular-esm-dynamic-impor.patch b/vscode-paches/0021-fix-replace-amd-imports-by-regular-esm-dynamic-impor.patch new file mode 100644 index 00000000..a9cc81b4 --- /dev/null +++ b/vscode-paches/0021-fix-replace-amd-imports-by-regular-esm-dynamic-impor.patch @@ -0,0 +1,191 @@ +From 59061c511d5a8f0540bf414e483f29aa8f4155d3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:22:31 +0100 +Subject: [PATCH 21/58] fix: replace amd imports by regular esm dynamic imports + +--- + .eslintrc.json | 8 -------- + .../platform/assignment/common/assignmentService.ts | 3 +-- + src/vs/platform/telemetry/common/1dsAppender.ts | 5 ++--- + .../contrib/terminal/browser/terminalInstance.ts | 3 +-- + .../contrib/terminal/browser/xterm/xtermTerminal.ts | 13 ++++++------- + .../browser/terminalStickyScrollOverlay.ts | 5 ++--- + 6 files changed, 12 insertions(+), 25 deletions(-) + +diff --git a/.eslintrc.json b/.eslintrc.json +index 59769eeda54..5ad0c3fe46c 100644 +--- a/.eslintrc.json ++++ b/.eslintrc.json +@@ -297,14 +297,6 @@ + "jsdoc/require-returns": "warn" + } + }, +- { +- "files": [ +- "src/**/{common,browser}/**/*.ts" +- ], +- "rules": { +- "local/code-amd-node-module": "warn" +- } +- }, + { + "files": [ + "src/**/{browser,electron-sandbox}/**/*.ts" +diff --git a/src/vs/platform/assignment/common/assignmentService.ts b/src/vs/platform/assignment/common/assignmentService.ts +index c573b727e0b..8c52126a590 100644 +--- a/src/vs/platform/assignment/common/assignmentService.ts ++++ b/src/vs/platform/assignment/common/assignmentService.ts +@@ -9,7 +9,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur + import { IProductService } from 'vs/platform/product/common/productService'; + import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils'; + import { AssignmentFilterProvider, ASSIGNMENT_REFETCH_INTERVAL, ASSIGNMENT_STORAGE_KEY, IAssignmentService, TargetPopulation } from 'vs/platform/assignment/common/assignment'; +-import { importAMDNodeModule } from 'vs/amdX'; + import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + + export abstract class BaseAssignmentService implements IAssignmentService { +@@ -88,7 +87,7 @@ export abstract class BaseAssignmentService implements IAssignmentService { + ); + + const tasConfig = this.productService.tasConfig!; +- const tasClient = new (await importAMDNodeModule('tas-client-umd', 'lib/tas-client-umd.js')).ExperimentationService({ ++ const tasClient = new (await import('tas-client-umd')).ExperimentationService({ + filterProviders: [filterProvider], + telemetry: this.telemetry, + storageKey: ASSIGNMENT_STORAGE_KEY, +diff --git a/src/vs/platform/telemetry/common/1dsAppender.ts b/src/vs/platform/telemetry/common/1dsAppender.ts +index c54187f89c9..a4729fabe2e 100644 +--- a/src/vs/platform/telemetry/common/1dsAppender.ts ++++ b/src/vs/platform/telemetry/common/1dsAppender.ts +@@ -5,7 +5,6 @@ + + import type { IExtendedConfiguration, IExtendedTelemetryItem, ITelemetryItem, ITelemetryUnloadState } from '@microsoft/1ds-core-js'; + import type { IChannelConfiguration, IXHROverride, PostChannel } from '@microsoft/1ds-post-js'; +-import { importAMDNodeModule } from 'vs/amdX'; + import { onUnexpectedError } from 'vs/base/common/errors'; + import { mixin } from 'vs/base/common/objects'; + import { ITelemetryAppender, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils'; +@@ -22,8 +21,8 @@ const endpointUrl = 'https://mobile.events.data.microsoft.com/OneCollector/1.0'; + const endpointHealthUrl = 'https://mobile.events.data.microsoft.com/ping'; + + async function getClient(instrumentationKey: string, addInternalFlag?: boolean, xhrOverride?: IXHROverride): Promise { +- const oneDs = await importAMDNodeModule('@microsoft/1ds-core-js', 'dist/ms.core.js'); +- const postPlugin = await importAMDNodeModule('@microsoft/1ds-post-js', 'dist/ms.post.js'); ++ const oneDs = await import('@microsoft/1ds-core-js'); ++ const postPlugin = await import('@microsoft/1ds-post-js'); + const appInsightsCore = new oneDs.AppInsightsCore(); + const collectorChannelPlugin: PostChannel = new postPlugin.PostChannel(); + // Configure the app insights core to send to collector++ and disable logging of debug info +diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +index 84bde0d8006..941c88582cb 100644 +--- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts ++++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +@@ -83,7 +83,6 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history'; + import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; + import { IPathService } from 'vs/workbench/services/path/common/pathService'; + import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; +-import { importAMDNodeModule } from 'vs/amdX'; + import type { IMarker, Terminal as XTermTerminal } from '@xterm/xterm'; + import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands'; + import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings'; +@@ -703,7 +702,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { + return xtermConstructor; + } + xtermConstructor = Promises.withAsyncBody(async (resolve) => { +- const Terminal = (await importAMDNodeModule('@xterm/xterm', 'lib/xterm.js')).Terminal; ++ const Terminal = (await import('@xterm/xterm')).Terminal; + // Localize strings + Terminal.strings.promptLabel = nls.localize('terminal.integrated.a11yPromptLabel', 'Terminal input'); + Terminal.strings.tooMuchOutput = keybinding ? nls.localize('terminal.integrated.useAccessibleBuffer', 'Use the accessible buffer {0} to manually review output', keybinding.getLabel()) : nls.localize('terminal.integrated.useAccessibleBufferNoKb', 'Use the Terminal: Focus Accessible Buffer command to manually review output'); +diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +index 0f2ef8f01f4..a0d82d41170 100644 +--- a/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts ++++ b/src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts +@@ -35,7 +35,6 @@ import { DecorationAddon } from 'vs/workbench/contrib/terminal/browser/xterm/dec + import { ITerminalCapabilityStore, ITerminalCommand, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; + import { Emitter } from 'vs/base/common/event'; + import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +-import { importAMDNodeModule } from 'vs/amdX'; + import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; + import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; + import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +@@ -754,7 +753,7 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach + + protected async _getCanvasAddonConstructor(): Promise { + if (!CanvasAddon) { +- CanvasAddon = (await importAMDNodeModule('@xterm/addon-canvas', 'lib/xterm-addon-canvas.js')).CanvasAddon; ++ CanvasAddon = (await import('@xterm/addon-canvas')).CanvasAddon; + } + return CanvasAddon; + } +@@ -780,35 +779,35 @@ export class XtermTerminal extends Disposable implements IXtermTerminal, IDetach + + protected async _getImageAddonConstructor(): Promise { + if (!ImageAddon) { +- ImageAddon = (await importAMDNodeModule('@xterm/addon-image', 'lib/addon-image.js')).ImageAddon; ++ ImageAddon = (await import('@xterm/addon-image')).ImageAddon; + } + return ImageAddon; + } + + protected async _getSearchAddonConstructor(): Promise { + if (!SearchAddon) { +- SearchAddon = (await importAMDNodeModule('@xterm/addon-search', 'lib/addon-search.js')).SearchAddon; ++ SearchAddon = (await import('@xterm/addon-search')).SearchAddon; + } + return SearchAddon; + } + + protected async _getUnicode11Constructor(): Promise { + if (!Unicode11Addon) { +- Unicode11Addon = (await importAMDNodeModule('@xterm/addon-unicode11', 'lib/addon-unicode11.js')).Unicode11Addon; ++ Unicode11Addon = (await import('@xterm/addon-unicode11')).Unicode11Addon; + } + return Unicode11Addon; + } + + protected async _getWebglAddonConstructor(): Promise { + if (!WebglAddon) { +- WebglAddon = (await importAMDNodeModule('@xterm/addon-webgl', 'lib/addon-webgl.js')).WebglAddon; ++ WebglAddon = (await import('@xterm/addon-webgl')).WebglAddon; + } + return WebglAddon; + } + + protected async _getSerializeAddonConstructor(): Promise { + if (!SerializeAddon) { +- SerializeAddon = (await importAMDNodeModule('@xterm/addon-serialize', 'lib/addon-serialize.js')).SerializeAddon; ++ SerializeAddon = (await import('@xterm/addon-serialize')).SerializeAddon; + } + return SerializeAddon; + } +diff --git a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts +index 8868f63beef..6aaa5c0c2df 100644 +--- a/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts ++++ b/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.ts +@@ -5,7 +5,6 @@ + import type { CanvasAddon as CanvasAddonType } from '@xterm/addon-canvas'; + import type { SerializeAddon as SerializeAddonType } from '@xterm/addon-serialize'; + import type { IBufferLine, IMarker, ITerminalOptions, ITheme, Terminal as RawXtermTerminal, Terminal as XTermTerminal } from '@xterm/xterm'; +-import { importAMDNodeModule } from 'vs/amdX'; + import { $, addDisposableListener, addStandardDisposableListener, getWindow } from 'vs/base/browser/dom'; + import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; + import { debounce, memoize, throttle } from 'vs/base/common/decorators'; +@@ -467,13 +466,13 @@ export class TerminalStickyScrollOverlay extends Disposable { + + @memoize + private async _getCanvasAddonConstructor(): Promise { +- const m = await importAMDNodeModule('@xterm/addon-canvas', 'lib/xterm-addon-canvas.js'); ++ const m = await import('@xterm/addon-canvas'); + return m.CanvasAddon; + } + + @memoize + private async _getSerializeAddonConstructor(): Promise { +- const m = await importAMDNodeModule('@xterm/addon-serialize', 'lib/addon-serialize.js'); ++ const m = await import('@xterm/addon-serialize'); + return m.SerializeAddon; + } + } +-- +2.34.1 + diff --git a/vscode-paches/0022-fix-update-import-syntax-for-node-in-ESM.patch b/vscode-paches/0022-fix-update-import-syntax-for-node-in-ESM.patch new file mode 100644 index 00000000..bcc5a60f --- /dev/null +++ b/vscode-paches/0022-fix-update-import-syntax-for-node-in-ESM.patch @@ -0,0 +1,126 @@ +From 7468c893deb4e3b64b399318a0b8b1efc0d7f764 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:23:59 +0100 +Subject: [PATCH 22/58] fix: update import syntax for node in ESM + +--- + src/vs/platform/environment/node/argv.ts | 2 +- + src/vs/platform/environment/node/argvHelper.ts | 2 +- + .../platform/native/electron-main/nativeHostMainService.ts | 2 +- + src/vs/platform/terminal/node/ptyService.ts | 7 ++++--- + src/vs/workbench/api/node/extHostExtensionService.ts | 7 ++++++- + src/vs/workbench/api/node/extensionHostProcess.ts | 2 +- + 6 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts +index 0d3a9795ffb..2cc1981808a 100644 +--- a/src/vs/platform/environment/node/argv.ts ++++ b/src/vs/platform/environment/node/argv.ts +@@ -3,7 +3,7 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import * as minimist from 'minimist'; ++import minimist from 'minimist'; + import { isWindows } from 'vs/base/common/platform'; + import { localize } from 'vs/nls'; + import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; +diff --git a/src/vs/platform/environment/node/argvHelper.ts b/src/vs/platform/environment/node/argvHelper.ts +index d8cefb6df67..a94fca911ea 100644 +--- a/src/vs/platform/environment/node/argvHelper.ts ++++ b/src/vs/platform/environment/node/argvHelper.ts +@@ -3,7 +3,7 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import * as assert from 'assert'; ++import assert from 'assert'; + import { IProcessEnvironment } from 'vs/base/common/platform'; + import { localize } from 'vs/nls'; + import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; +diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts +index a1d28301611..2ffbae2fd9c 100644 +--- a/src/vs/platform/native/electron-main/nativeHostMainService.ts ++++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts +@@ -495,7 +495,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain + async isAdmin(): Promise { + let isAdmin: boolean; + if (isWindows) { +- isAdmin = (await import('native-is-elevated'))(); ++ isAdmin = (await import('native-is-elevated')).default(); + } else { + isAdmin = process.getuid?.() === 0; + } +diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts +index ec8182b3c1d..85de100c7c0 100644 +--- a/src/vs/platform/terminal/node/ptyService.ts ++++ b/src/vs/platform/terminal/node/ptyService.ts +@@ -15,7 +15,8 @@ import { RequestStore } from 'vs/platform/terminal/common/requestStore'; + import { IProcessDataEvent, IProcessReadyEvent, IPtyService, IRawTerminalInstanceLayoutInfo, IReconnectConstants, IShellLaunchConfig, ITerminalInstanceLayoutInfoById, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalTabLayoutInfoById, TerminalIcon, IProcessProperty, TitleEventSource, ProcessPropertyType, IProcessPropertyMap, IFixedTerminalDimensions, IPersistentTerminalProcessLaunchConfig, ICrossVersionSerializedTerminalState, ISerializedTerminalState, ITerminalProcessOptions, IPtyHostLatencyMeasurement } from 'vs/platform/terminal/common/terminal'; + import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; + import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment'; +-import { Terminal as XtermTerminal } from '@xterm/headless'; ++// Fix/Hack for xterm being build as umd ++import xtermHeadless from '@xterm/headless'; + import type { ISerializeOptions, SerializeAddon as XtermSerializeAddon } from '@xterm/addon-serialize'; + import type { Unicode11Addon as XtermUnicode11Addon } from '@xterm/addon-unicode11'; + import { IGetTerminalLayoutInfoArgs, IProcessDetails, ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto } from 'vs/platform/terminal/common/terminalProcess'; +@@ -976,7 +977,7 @@ class MutationLogger { + } + + class XtermSerializer implements ITerminalSerializer { +- private readonly _xterm: XtermTerminal; ++ private readonly _xterm: xtermHeadless.Terminal; + private readonly _shellIntegrationAddon: ShellIntegrationAddon; + private _unicodeAddon?: XtermUnicode11Addon; + +@@ -990,7 +991,7 @@ class XtermSerializer implements ITerminalSerializer { + private _rawReviveBuffer: string | undefined, + logService: ILogService + ) { +- this._xterm = new XtermTerminal({ ++ this._xterm = new xtermHeadless.Terminal({ + cols, + rows, + scrollback, +diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts +index 5ac0ddc7ec9..6ea024b237b 100644 +--- a/src/vs/workbench/api/node/extHostExtensionService.ts ++++ b/src/vs/workbench/api/node/extHostExtensionService.ts +@@ -19,6 +19,11 @@ import { realpathSync } from 'vs/base/node/extpath'; + import { ExtHostConsoleForwarder } from 'vs/workbench/api/node/extHostConsoleForwarder'; + import { ExtHostDiskFileSystemProvider } from 'vs/workbench/api/node/extHostDiskFileSystemProvider'; + ++// ESM-uncomment-begin ++// import { createRequire } from 'node:module'; ++// globalThis.require = createRequire(import.meta.url); ++// ESM-uncomment-end ++ + class NodeModuleRequireInterceptor extends RequireInterceptor { + + protected _installInterceptor(): void { +@@ -109,7 +114,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { + if (extensionId) { + performance.mark(`code/extHost/willLoadExtensionCode/${extensionId}`); + } +- r = require.__$__nodeRequire(module.fsPath); ++ r = await require(module.fsPath); + } finally { + if (extensionId) { + performance.mark(`code/extHost/didLoadExtensionCode/${extensionId}`); +diff --git a/src/vs/workbench/api/node/extensionHostProcess.ts b/src/vs/workbench/api/node/extensionHostProcess.ts +index 785db7edd43..c98941f5181 100644 +--- a/src/vs/workbench/api/node/extensionHostProcess.ts ++++ b/src/vs/workbench/api/node/extensionHostProcess.ts +@@ -5,7 +5,7 @@ + + import * as nativeWatchdog from 'native-watchdog'; + import * as net from 'net'; +-import * as minimist from 'minimist'; ++import minimist from 'minimist'; + import * as performance from 'vs/base/common/performance'; + import type { MessagePortMain } from 'vs/base/parts/sandbox/node/electronTypes'; + import { isCancellationError, isSigPipeError, onUnexpectedError } from 'vs/base/common/errors'; +-- +2.34.1 + diff --git a/vscode-paches/0023-fixup-feat-add-static-asset-url-mechanism.patch b/vscode-paches/0023-fixup-feat-add-static-asset-url-mechanism.patch new file mode 100644 index 00000000..5b03c7cf --- /dev/null +++ b/vscode-paches/0023-fixup-feat-add-static-asset-url-mechanism.patch @@ -0,0 +1,24 @@ +From a6f7a2e8627c5efc106d95066b2bfe4f6f70b930 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:25:46 +0100 +Subject: [PATCH 23/58] fixup! feat: add static asset url mechanism + +--- + src/vs/workbench/api/common/extHost.protocol.ts | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts +index 5c18ab8657a..d7f00aaca84 100644 +--- a/src/vs/workbench/api/common/extHost.protocol.ts ++++ b/src/vs/workbench/api/common/extHost.protocol.ts +@@ -1436,6 +1436,7 @@ export interface MainThreadExtensionServiceShape extends IDisposable { + $onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void; + $setPerformanceMarks(marks: performance.PerformanceMark[]): Promise; + $asBrowserUri(uri: UriComponents): Promise; ++ $getAllStaticBrowserUris(): Promise<[UriComponents, UriComponents][]>; + } + + export interface SCMProviderFeatures { +-- +2.34.1 + diff --git a/vscode-paches/0024-feat-export-some-classes-and-make-some-methods-acces.patch b/vscode-paches/0024-feat-export-some-classes-and-make-some-methods-acces.patch new file mode 100644 index 00000000..7100f2c1 --- /dev/null +++ b/vscode-paches/0024-feat-export-some-classes-and-make-some-methods-acces.patch @@ -0,0 +1,374 @@ +From 1136962265c165887f318ba3d0f90eb9de2fea14 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:32:31 +0100 +Subject: [PATCH 24/58] feat: export some classes and make some methods + accessible + +--- + .../browser/extensionResourceLoaderService.ts | 2 +- + .../workbench/api/browser/statusBarExtensionPoint.ts | 2 +- + src/vs/workbench/browser/layout.ts | 10 +++++----- + src/vs/workbench/browser/workbench.ts | 12 ++++++------ + .../debug/browser/extensionHostDebugService.ts | 2 +- + .../contrib/logs/common/defaultLogLevels.ts | 2 +- + .../extensionManagement/browser/extensionBisect.ts | 2 +- + .../services/extensions/browser/extensionService.ts | 2 +- + .../extensions/browser/extensionUrlHandler.ts | 2 +- + .../extensions/browser/webWorkerExtensionHost.ts | 2 +- + .../extensions/common/abstractExtensionService.ts | 10 +++++----- + .../services/keybinding/browser/keybindingService.ts | 2 +- + .../languageStatus/common/languageStatusService.ts | 2 +- + .../services/outline/browser/outlineService.ts | 2 +- + .../services/remote/common/remoteExplorerService.ts | 2 +- + .../remote/common/remoteExtensionsScanner.ts | 2 +- + .../terminal/common/embedderTerminalService.ts | 2 +- + .../userDataProfile/common/remoteUserDataProfiles.ts | 2 +- + .../services/userDataSync/common/userDataSyncUtil.ts | 2 +- + 19 files changed, 32 insertions(+), 32 deletions(-) + +diff --git a/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts b/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts +index fdefc170db0..1d3bc4affc5 100644 +--- a/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts ++++ b/src/vs/platform/extensionResourceLoader/browser/extensionResourceLoaderService.ts +@@ -14,7 +14,7 @@ import { ILogService } from 'vs/platform/log/common/log'; + import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; + import { AbstractExtensionResourceLoaderService, IExtensionResourceLoaderService } from 'vs/platform/extensionResourceLoader/common/extensionResourceLoader'; + +-class ExtensionResourceLoaderService extends AbstractExtensionResourceLoaderService { ++export class ExtensionResourceLoaderService extends AbstractExtensionResourceLoaderService { + + declare readonly _serviceBrand: undefined; + +diff --git a/src/vs/workbench/api/browser/statusBarExtensionPoint.ts b/src/vs/workbench/api/browser/statusBarExtensionPoint.ts +index 99dd3279fe8..b692381eaa2 100644 +--- a/src/vs/workbench/api/browser/statusBarExtensionPoint.ts ++++ b/src/vs/workbench/api/browser/statusBarExtensionPoint.ts +@@ -57,7 +57,7 @@ export interface IExtensionStatusBarItemService { + } + + +-class ExtensionStatusBarItemService implements IExtensionStatusBarItemService { ++export class ExtensionStatusBarItemService implements IExtensionStatusBarItemService { + + declare readonly _serviceBrand: undefined; + +diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts +index a2b6007fb79..4ee25602224 100644 +--- a/src/vs/workbench/browser/layout.ts ++++ b/src/vs/workbench/browser/layout.ts +@@ -52,7 +52,7 @@ import { CustomTitleBarVisibility } from '../../platform/window/common/window'; + + //#region Layout Implementation + +-interface ILayoutRuntimeState { ++export interface ILayoutRuntimeState { + activeContainerId: number; + mainWindowFullscreen: boolean; + readonly maximized: Set; +@@ -66,12 +66,12 @@ interface ILayoutRuntimeState { + }; + } + +-interface IEditorToOpen { ++export interface IEditorToOpen { + readonly editor: IUntypedEditorInput; + readonly viewColumn?: number; + } + +-interface ILayoutInitializationState { ++export interface ILayoutInitializationState { + readonly views: { + readonly defaults: string[] | undefined; + readonly containerToRestore: { +@@ -105,11 +105,11 @@ enum LayoutClasses { + WINDOW_BORDER = 'border' + } + +-interface IPathToOpen extends IPath { ++export interface IPathToOpen extends IPath { + readonly viewColumn?: number; + } + +-interface IInitialEditorsState { ++export interface IInitialEditorsState { + readonly filesToOpenOrCreate?: IPathToOpen[]; + readonly filesToDiff?: IPathToOpen[]; + readonly filesToMerge?: IPathToOpen[]; +diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts +index 8a311d4bb0e..56e9b6f58cf 100644 +--- a/src/vs/workbench/browser/workbench.ts ++++ b/src/vs/workbench/browser/workbench.ts +@@ -76,7 +76,7 @@ export class Workbench extends Layout { + this.registerErrorHandler(logService); + } + +- private registerErrorHandler(logService: ILogService): void { ++ protected registerErrorHandler(logService: ILogService): void { + + // Listen on unhandled rejection events + this._register(addDisposableListener(mainWindow, 'unhandledrejection', event => { +@@ -192,7 +192,7 @@ export class Workbench extends Layout { + } + } + +- private initServices(serviceCollection: ServiceCollection): IInstantiationService { ++ protected initServices(serviceCollection: ServiceCollection): IInstantiationService { + + // Layout Service + serviceCollection.set(IWorkbenchLayoutService, this); +@@ -231,7 +231,7 @@ export class Workbench extends Layout { + return instantiationService; + } + +- private registerListeners(lifecycleService: ILifecycleService, storageService: IStorageService, configurationService: IConfigurationService, hostService: IHostService, dialogService: IDialogService): void { ++ protected registerListeners(lifecycleService: ILifecycleService, storageService: IStorageService, configurationService: IConfigurationService, hostService: IHostService, dialogService: IDialogService): void { + + // Configuration changes + this._register(configurationService.onDidChangeConfiguration(e => this.updateFontAliasing(e, configurationService))); +@@ -320,7 +320,7 @@ export class Workbench extends Layout { + } + } + +- private renderWorkbench(instantiationService: IInstantiationService, notificationService: NotificationService, storageService: IStorageService, configurationService: IConfigurationService): void { ++ protected renderWorkbench(instantiationService: IInstantiationService, notificationService: NotificationService, storageService: IStorageService, configurationService: IConfigurationService): void { + + // ARIA + setARIAContainer(this.mainContainer); +@@ -386,7 +386,7 @@ export class Workbench extends Layout { + return part; + } + +- private createNotificationsHandlers(instantiationService: IInstantiationService, notificationService: NotificationService): void { ++ protected createNotificationsHandlers(instantiationService: IInstantiationService, notificationService: NotificationService): void { + + // Instantiate Notification components + const notificationsCenter = this._register(instantiationService.createInstance(NotificationsCenter, this.mainContainer, notificationService.model)); +@@ -414,7 +414,7 @@ export class Workbench extends Layout { + }); + } + +- private restore(lifecycleService: ILifecycleService): void { ++ protected restore(lifecycleService: ILifecycleService): void { + + // Ask each part to restore + try { +diff --git a/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts b/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts +index 08449bd2cd7..f82ac191725 100644 +--- a/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts ++++ b/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts +@@ -19,7 +19,7 @@ import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/envir + import { IHostService } from 'vs/workbench/services/host/browser/host'; + import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; + +-class BrowserExtensionHostDebugService extends ExtensionHostDebugChannelClient implements IExtensionHostDebugService { ++export class BrowserExtensionHostDebugService extends ExtensionHostDebugChannelClient implements IExtensionHostDebugService { + + private static readonly LAST_EXTENSION_DEVELOPMENT_WORKSPACE_KEY = 'debug.lastExtensionDevelopmentWorkspace'; + +diff --git a/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts b/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts +index 9feccec6965..64b9e5d3ed0 100644 +--- a/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts ++++ b/src/vs/workbench/contrib/logs/common/defaultLogLevels.ts +@@ -33,7 +33,7 @@ export interface IDefaultLogLevelsService { + migrateLogLevels(): void; + } + +-class DefaultLogLevelsService implements IDefaultLogLevelsService { ++export class DefaultLogLevelsService implements IDefaultLogLevelsService { + + _serviceBrand: undefined; + +diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts +index caf3def4700..232570b93fa 100644 +--- a/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts ++++ b/src/vs/workbench/services/extensionManagement/browser/extensionBisect.ts +@@ -65,7 +65,7 @@ class BisectState { + ) { } + } + +-class ExtensionBisectService implements IExtensionBisectService { ++export class ExtensionBisectService implements IExtensionBisectService { + + declare readonly _serviceBrand: undefined; + +diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts +index a181772e8c4..27b6797fd78 100644 +--- a/src/vs/workbench/services/extensions/browser/extensionService.ts ++++ b/src/vs/workbench/services/extensions/browser/extensionService.ts +@@ -249,7 +249,7 @@ class BrowserExtensionHostFactory implements IExtensionHostFactory { + } + } + +- private _createLocalExtensionHostDataProvider(runningLocations: ExtensionRunningLocationTracker, desiredRunningLocation: ExtensionRunningLocation, isInitialStart: boolean): IWebWorkerExtensionHostDataProvider { ++ protected _createLocalExtensionHostDataProvider(runningLocations: ExtensionRunningLocationTracker, desiredRunningLocation: ExtensionRunningLocation, isInitialStart: boolean): IWebWorkerExtensionHostDataProvider { + return { + getInitData: async (): Promise => { + if (isInitialStart) { +diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +index d019d14c4fb..78d4a00fa7f 100644 +--- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts ++++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +@@ -98,7 +98,7 @@ type ExtensionUrlHandlerClassification = { + * + * It also makes sure the user confirms opening URLs directed towards extensions. + */ +-class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { ++export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { + + readonly _serviceBrand: undefined; + +diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +index b6d4f0f3831..a5f5e42eddd 100644 +--- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts ++++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +@@ -76,7 +76,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost + this._extensionHostLogsLocation = joinPath(this._environmentService.extHostLogsPath, 'webWorker'); + } + +- private async _getWebWorkerExtensionHostIframeSrc(): Promise { ++ protected async _getWebWorkerExtensionHostIframeSrc(): Promise { + const suffixSearchParams = new URLSearchParams(); + if (this._environmentService.debugExtensionHost && this._environmentService.debugRenderer) { + suffixSearchParams.set('debugged', '1'); +diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +index 2d93e41d0f0..0abfe0b61a3 100644 +--- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts ++++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +@@ -94,9 +94,9 @@ export abstract class AbstractExtensionService extends Disposable implements IEx + private _resolveAuthorityAttempt: number = 0; + + constructor( +- private readonly _extensionsProposedApi: ExtensionsProposedApi, +- private readonly _extensionHostFactory: IExtensionHostFactory, +- private readonly _extensionHostKindPicker: IExtensionHostKindPicker, ++ protected readonly _extensionsProposedApi: ExtensionsProposedApi, ++ protected readonly _extensionHostFactory: IExtensionHostFactory, ++ protected readonly _extensionHostKindPicker: IExtensionHostKindPicker, + @IInstantiationService protected readonly _instantiationService: IInstantiationService, + @INotificationService protected readonly _notificationService: INotificationService, + @IWorkbenchEnvironmentService protected readonly _environmentService: IWorkbenchEnvironmentService, +@@ -211,7 +211,7 @@ export abstract class AbstractExtensionService extends Disposable implements IEx + + //#region deltaExtensions + +- private async _handleDeltaExtensions(item: DeltaExtensionsQueueItem): Promise { ++ protected async _handleDeltaExtensions(item: DeltaExtensionsQueueItem): Promise { + this._deltaExtensionsQueue.push(item); + if (this._inHandleDeltaExtensions) { + // Let the current item finish, the new one will be picked up +@@ -1193,7 +1193,7 @@ export interface IExtensionHostFactory { + createExtensionHost(runningLocations: ExtensionRunningLocationTracker, runningLocation: ExtensionRunningLocation, isInitialStart: boolean): IExtensionHost | null; + } + +-class DeltaExtensionsQueueItem { ++export class DeltaExtensionsQueueItem { + constructor( + public readonly toAdd: IExtension[], + public readonly toRemove: string[] | IExtension[] +diff --git a/src/vs/workbench/services/keybinding/browser/keybindingService.ts b/src/vs/workbench/services/keybinding/browser/keybindingService.ts +index 708268ba3c3..cbed3a6137c 100644 +--- a/src/vs/workbench/services/keybinding/browser/keybindingService.ts ++++ b/src/vs/workbench/services/keybinding/browser/keybindingService.ts +@@ -423,7 +423,7 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { + return this.userKeybindings.keybindings.length; + } + +- private updateResolver(): void { ++ protected updateResolver(): void { + this._cachedResolver = null; + this._onDidUpdateKeybindings.fire(); + } +diff --git a/src/vs/workbench/services/languageStatus/common/languageStatusService.ts b/src/vs/workbench/services/languageStatus/common/languageStatusService.ts +index e10d2a3ef1e..6dd88102a64 100644 +--- a/src/vs/workbench/services/languageStatus/common/languageStatusService.ts ++++ b/src/vs/workbench/services/languageStatus/common/languageStatusService.ts +@@ -47,7 +47,7 @@ export interface ILanguageStatusService { + } + + +-class LanguageStatusServiceImpl implements ILanguageStatusService { ++export class LanguageStatusServiceImpl implements ILanguageStatusService { + + declare _serviceBrand: undefined; + +diff --git a/src/vs/workbench/services/outline/browser/outlineService.ts b/src/vs/workbench/services/outline/browser/outlineService.ts +index f4707432371..7c5cdde39cc 100644 +--- a/src/vs/workbench/services/outline/browser/outlineService.ts ++++ b/src/vs/workbench/services/outline/browser/outlineService.ts +@@ -11,7 +11,7 @@ import { IEditorPane } from 'vs/workbench/common/editor'; + import { IOutline, IOutlineCreator, IOutlineService, OutlineTarget } from 'vs/workbench/services/outline/browser/outline'; + import { Event, Emitter } from 'vs/base/common/event'; + +-class OutlineService implements IOutlineService { ++export class OutlineService implements IOutlineService { + + declare _serviceBrand: undefined; + +diff --git a/src/vs/workbench/services/remote/common/remoteExplorerService.ts b/src/vs/workbench/services/remote/common/remoteExplorerService.ts +index be889244846..875a9072cf0 100644 +--- a/src/vs/workbench/services/remote/common/remoteExplorerService.ts ++++ b/src/vs/workbench/services/remote/common/remoteExplorerService.ts +@@ -139,7 +139,7 @@ export interface IRemoteExplorerService { + readonly namedProcesses: Map; + } + +-class RemoteExplorerService implements IRemoteExplorerService { ++export class RemoteExplorerService implements IRemoteExplorerService { + public _serviceBrand: undefined; + private _targetType: string[] = []; + private readonly _onDidChangeTargetType: Emitter = new Emitter(); +diff --git a/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts b/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts +index a466cc1f3a1..09f6a40eb26 100644 +--- a/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts ++++ b/src/vs/workbench/services/remote/common/remoteExtensionsScanner.ts +@@ -16,7 +16,7 @@ import { ILogService } from 'vs/platform/log/common/log'; + import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; + import { IActiveLanguagePackService } from 'vs/workbench/services/localization/common/locale'; + +-class RemoteExtensionsScannerService implements IRemoteExtensionsScannerService { ++export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerService { + + declare readonly _serviceBrand: undefined; + +diff --git a/src/vs/workbench/services/terminal/common/embedderTerminalService.ts b/src/vs/workbench/services/terminal/common/embedderTerminalService.ts +index 5e322af7a0f..07b4abdd636 100644 +--- a/src/vs/workbench/services/terminal/common/embedderTerminalService.ts ++++ b/src/vs/workbench/services/terminal/common/embedderTerminalService.ts +@@ -52,7 +52,7 @@ export interface IEmbedderTerminalPty { + // setDimensions?(dimensions: TerminalDimensions): void; + } + +-class EmbedderTerminalService implements IEmbedderTerminalService { ++export class EmbedderTerminalService implements IEmbedderTerminalService { + declare _serviceBrand: undefined; + + private readonly _onDidCreateTerminal = new Emitter(); +diff --git a/src/vs/workbench/services/userDataProfile/common/remoteUserDataProfiles.ts b/src/vs/workbench/services/userDataProfile/common/remoteUserDataProfiles.ts +index d3ef612836b..0d0fb8d2862 100644 +--- a/src/vs/workbench/services/userDataProfile/common/remoteUserDataProfiles.ts ++++ b/src/vs/workbench/services/userDataProfile/common/remoteUserDataProfiles.ts +@@ -25,7 +25,7 @@ export interface IRemoteUserDataProfilesService { + getRemoteProfile(localProfile: IUserDataProfile): Promise; + } + +-class RemoteUserDataProfilesService extends Disposable implements IRemoteUserDataProfilesService { ++export class RemoteUserDataProfilesService extends Disposable implements IRemoteUserDataProfilesService { + + readonly _serviceBrand: undefined; + +diff --git a/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts b/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts +index 45329df40c4..84119b7c042 100644 +--- a/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts ++++ b/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.ts +@@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; + import { ITextModelService } from 'vs/editor/common/services/resolverService'; + import { ITextResourcePropertiesService, ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; + +-class UserDataSyncUtilService implements IUserDataSyncUtilService { ++export class UserDataSyncUtilService implements IUserDataSyncUtilService { + + declare readonly _serviceBrand: undefined; + +-- +2.34.1 + diff --git a/vscode-paches/0025-fixup-fix-replace-amd-imports-by-regular-esm-dynamic.patch b/vscode-paches/0025-fixup-fix-replace-amd-imports-by-regular-esm-dynamic.patch new file mode 100644 index 00000000..476f14ef --- /dev/null +++ b/vscode-paches/0025-fixup-fix-replace-amd-imports-by-regular-esm-dynamic.patch @@ -0,0 +1,199 @@ +From b3ac0ff98eccedf2efcfe67a64b15008343b64f6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:36:13 +0100 +Subject: [PATCH 25/58] fixup! fix: replace amd imports by regular esm dynamic + imports + +--- + .eslintrc.json | 1 + + .../textMateWorkerTokenizerController.ts | 4 +--- + .../worker/textMateTokenizationWorker.worker.ts | 12 +++++------- + .../worker/textMateWorkerTokenizer.ts | 4 +--- + .../browser/textMateTokenizationFeatureImpl.ts | 14 +++++++------- + 5 files changed, 15 insertions(+), 20 deletions(-) + +diff --git a/.eslintrc.json b/.eslintrc.json +index 5ad0c3fe46c..5ed8297cf46 100644 +--- a/.eslintrc.json ++++ b/.eslintrc.json +@@ -852,6 +852,7 @@ + }, // TODO@layers + "tas-client-umd", // node module allowed even in /common/ + "vscode-textmate", // node module allowed even in /common/ ++ "vscode-oniguruma", + "@vscode/vscode-languagedetection" // node module allowed even in /common/ + ] + }, +diff --git a/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts b/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts +index 850b58e1e6c..2eb835fa2b6 100644 +--- a/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts ++++ b/src/vs/workbench/services/textMate/browser/backgroundTokenization/textMateWorkerTokenizerController.ts +@@ -3,7 +3,6 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import { importAMDNodeModule } from 'vs/amdX'; + import { Disposable } from 'vs/base/common/lifecycle'; + import { IObservable, autorun, keepObserved, observableFromEvent } from 'vs/base/common/observable'; + import { countEOL } from 'vs/editor/common/core/eolCounter'; +@@ -17,7 +16,7 @@ import { ContiguousMultilineTokensBuilder } from 'vs/editor/common/tokens/contig + import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; + import { ArrayEdit, MonotonousIndexTransformer, SingleArrayEdit } from 'vs/workbench/services/textMate/browser/arrayOperation'; + import type { StateDeltas, TextMateTokenizationWorker } from 'vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker'; +-import type { applyStateStackDiff, StateStack } from 'vscode-textmate'; ++import { StateStack, applyStateStackDiff, INITIAL } from 'vscode-textmate'; + + export class TextMateWorkerTokenizerController extends Disposable { + private static _id = 0; +@@ -178,7 +177,6 @@ export class TextMateWorkerTokenizerController extends Disposable { + ); + + if (!this._applyStateStackDiffFn || !this._initialState) { +- const { applyStateStackDiff, INITIAL } = await importAMDNodeModule('vscode-textmate', 'release/main.js'); + this._applyStateStackDiffFn = applyStateStackDiff; + this._initialState = INITIAL; + } +diff --git a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts +index 3974d642732..b391a7cda58 100644 +--- a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts ++++ b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker.ts +@@ -9,8 +9,9 @@ import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel'; + import { IWorkerContext } from 'vs/editor/common/services/editorSimpleWorker'; + import { ICreateGrammarResult, TMGrammarFactory } from 'vs/workbench/services/textMate/common/TMGrammarFactory'; + import { IValidEmbeddedLanguagesMap, IValidGrammarDefinition, IValidTokenTypeMap } from 'vs/workbench/services/textMate/common/TMScopeRegistry'; +-import type { IOnigLib, IRawTheme, StackDiff } from 'vscode-textmate'; + import { TextMateWorkerTokenizer } from './textMateWorkerTokenizer'; ++import * as vscodeTextmate from 'vscode-textmate'; ++import * as vscodeOniguruma from 'vscode-oniguruma'; + + /** + * Defines the worker entry point. Must be exported and named `create`. +@@ -47,7 +48,7 @@ export interface IValidGrammarDefinitionDTO { + export interface StateDeltas { + startLineNumber: number; + // null means the state for that line did not change +- stateDeltas: (StackDiff | null)[]; ++ stateDeltas: (vscodeTextmate.StackDiff | null)[]; + } + + export class TextMateTokenizationWorker { +@@ -78,9 +79,6 @@ export class TextMateTokenizationWorker { + } + + private async _loadTMGrammarFactory(grammarDefinitions: IValidGrammarDefinition[]): Promise { +- const uri = this._createData.textmateMainUri; +- const vscodeTextmate = await import(uri); +- const vscodeOniguruma = await import(this._createData.onigurumaMainUri); + const response = await fetch(this._createData.onigurumaWASMUri); + + // Using the response directly only works if the server sets the MIME type 'application/wasm'. +@@ -89,7 +87,7 @@ export class TextMateTokenizationWorker { + const bytes = await response.arrayBuffer(); + await vscodeOniguruma.loadWASM(bytes); + +- const onigLib: Promise = Promise.resolve({ ++ const onigLib: Promise = Promise.resolve({ + createOnigScanner: (sources) => vscodeOniguruma.createOnigScanner(sources), + createOnigString: (str) => vscodeOniguruma.createOnigString(str) + }); +@@ -146,7 +144,7 @@ export class TextMateTokenizationWorker { + } + } + +- public async acceptTheme(theme: IRawTheme, colorMap: string[]): Promise { ++ public async acceptTheme(theme: vscodeTextmate.IRawTheme, colorMap: string[]): Promise { + const grammarFactory = await this._grammarFactory; + grammarFactory?.setTheme(theme, colorMap); + } +diff --git a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts +index bc98f7239ce..5937fa2286a 100644 +--- a/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts ++++ b/src/vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateWorkerTokenizer.ts +@@ -3,7 +3,6 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import { importAMDNodeModule } from 'vs/amdX'; + import { RunOnceScheduler } from 'vs/base/common/async'; + import { observableValue } from 'vs/base/common/observable'; + import { setTimeout0 } from 'vs/base/common/platform'; +@@ -16,7 +15,7 @@ import { ContiguousMultilineTokensBuilder } from 'vs/editor/common/tokens/contig + import { LineTokens } from 'vs/editor/common/tokens/lineTokens'; + import { TextMateTokenizationSupport } from 'vs/workbench/services/textMate/browser/tokenizationSupport/textMateTokenizationSupport'; + import { TokenizationSupportWithLineLimit } from 'vs/workbench/services/textMate/browser/tokenizationSupport/tokenizationSupportWithLineLimit'; +-import type { StackDiff, StateStack, diffStateStacksRefEq } from 'vscode-textmate'; ++import { StackDiff, StateStack, diffStateStacksRefEq } from 'vscode-textmate'; + import { ICreateGrammarResult } from 'vs/workbench/services/textMate/common/TMGrammarFactory'; + import { StateDeltas } from 'vs/workbench/services/textMate/browser/backgroundTokenization/worker/textMateTokenizationWorker.worker'; + +@@ -113,7 +112,6 @@ export class TextMateWorkerTokenizer extends MirrorTextModel { + } + + if (!this._diffStateStacksRefEqFn) { +- const { diffStateStacksRefEq } = await importAMDNodeModule('vscode-textmate', 'release/main.js'); + this._diffStateStacksRefEqFn = diffStateStacksRefEq; + } + +diff --git a/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts b/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts +index 1ba671448d2..9b682c0746c 100644 +--- a/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts ++++ b/src/vs/workbench/services/textMate/browser/textMateTokenizationFeatureImpl.ts +@@ -3,7 +3,6 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import { importAMDNodeModule } from 'vs/amdX'; + import * as dom from 'vs/base/browser/dom'; + import { equals as equalArray } from 'vs/base/common/arrays'; + import { Color } from 'vs/base/common/color'; +@@ -37,7 +36,8 @@ import { TMGrammarFactory, missingTMGrammarErrorMessage } from 'vs/workbench/ser + import { ITMSyntaxExtensionPoint, grammarsExtPoint } from 'vs/workbench/services/textMate/common/TMGrammars'; + import { IValidEmbeddedLanguagesMap, IValidGrammarDefinition, IValidTokenTypeMap } from 'vs/workbench/services/textMate/common/TMScopeRegistry'; + import { ITextMateThemingRule, IWorkbenchColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; +-import type { IGrammar, IOnigLib, IRawTheme } from 'vscode-textmate'; ++import * as vscodeTextmate from 'vscode-textmate'; ++import * as vscodeOniguruma from 'vscode-oniguruma'; + + export class TextMateTokenizationFeature extends Disposable implements ITextMateTokenizationService { + private static reportTokenizationTimeCounter = { sync: 0, async: 0 }; +@@ -53,7 +53,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate + private _grammarDefinitions: IValidGrammarDefinition[] | null = null; + private _grammarFactory: TMGrammarFactory | null = null; + private readonly _tokenizersRegistrations = new DisposableStore(); +- private _currentTheme: IRawTheme | null = null; ++ private _currentTheme: vscodeTextmate.IRawTheme | null = null; + private _currentTokenColorMap: string[] | null = null; + private readonly _threadedBackgroundTokenizerFactory = this._instantiationService.createInstance( + ThreadedBackgroundTokenizerFactory, +@@ -245,8 +245,8 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate + return this._grammarFactory; + } + +- const [vscodeTextmate, vscodeOniguruma] = await Promise.all([importAMDNodeModule('vscode-textmate', 'release/main.js'), this._getVSCodeOniguruma()]); +- const onigLib: Promise = Promise.resolve({ ++ const vscodeOniguruma = await this._getVSCodeOniguruma(); ++ const onigLib: Promise = Promise.resolve({ + createOnigScanner: (sources: string[]) => vscodeOniguruma.createOnigScanner(sources), + createOnigString: (str: string) => vscodeOniguruma.createOnigString(str) + }); +@@ -339,7 +339,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate + } + } + +- public async createTokenizer(languageId: string): Promise { ++ public async createTokenizer(languageId: string): Promise { + if (!this._languageService.isRegisteredLanguageId(languageId)) { + return null; + } +@@ -356,7 +356,7 @@ export class TextMateTokenizationFeature extends Disposable implements ITextMate + private _getVSCodeOniguruma(): Promise { + if (!this._vscodeOniguruma) { + this._vscodeOniguruma = (async () => { +- const [vscodeOniguruma, wasm] = await Promise.all([importAMDNodeModule('vscode-oniguruma', 'release/main.js'), this._loadVSCodeOnigurumaWASM()]); ++ const wasm = await this._loadVSCodeOnigurumaWASM(); + await vscodeOniguruma.loadWASM({ + data: wasm, + print: (str: string) => { +-- +2.34.1 + diff --git a/vscode-paches/0026-fixup-feat-export-some-classes-and-make-some-methods.patch b/vscode-paches/0026-fixup-feat-export-some-classes-and-make-some-methods.patch new file mode 100644 index 00000000..bd9edb56 --- /dev/null +++ b/vscode-paches/0026-fixup-feat-export-some-classes-and-make-some-methods.patch @@ -0,0 +1,26 @@ +From 1516c57b26b2fca65195323964d28ce6a7f6b949 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:37:43 +0100 +Subject: [PATCH 26/58] fixup! feat: export some classes and make some methods + accessible + +--- + .../common/extensionFeaturesManagemetService.ts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts b/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts +index 0e60b30cd13..a8fef74dbc4 100644 +--- a/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts ++++ b/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.ts +@@ -27,7 +27,7 @@ interface IExtensionFeatureState { + + const FEATURES_STATE_KEY = 'extension.features.state'; + +-class ExtensionFeaturesManagementService extends Disposable implements IExtensionFeaturesManagementService { ++export class ExtensionFeaturesManagementService extends Disposable implements IExtensionFeaturesManagementService { + declare readonly _serviceBrand: undefined; + + private readonly _onDidChangeEnablement = this._register(new Emitter<{ extension: ExtensionIdentifier; featureId: string; enabled: boolean }>()); +-- +2.34.1 + diff --git a/vscode-paches/0027-fix-improve-extension-contribution-types.patch b/vscode-paches/0027-fix-improve-extension-contribution-types.patch new file mode 100644 index 00000000..01b73581 --- /dev/null +++ b/vscode-paches/0027-fix-improve-extension-contribution-types.patch @@ -0,0 +1,1376 @@ +From 75a1252bf2979ab5475983ad380ecccd9288473c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:38:30 +0100 +Subject: [PATCH 27/58] fix: improve extension contribution types + +--- + .../platform/extensions/common/extensions.ts | 1194 ++++++++++++++++- + .../services/search/common/queryBuilder.ts | 8 +- + .../themes/common/colorExtensionPoint.ts | 2 +- + .../tokenClassificationExtensionPoint.ts | 1 + + 4 files changed, 1127 insertions(+), 78 deletions(-) + +diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts +index 413c1db06f1..c1667ac6c33 100644 +--- a/src/vs/platform/extensions/common/extensions.ts ++++ b/src/vs/platform/extensions/common/extensions.ts +@@ -3,6 +3,7 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + ++import { IJSONSchema } from 'vs/base/common/jsonSchema'; + import Severity from 'vs/base/common/severity'; + import * as strings from 'vs/base/common/strings'; + import { URI } from 'vs/base/common/uri'; +@@ -16,110 +17,496 @@ export const BUILTIN_MANIFEST_CACHE_FILE = 'extensions.builtin.cache'; + export const UNDEFINED_PUBLISHER = 'undefined_publisher'; + + export interface ICommand { +- command: string; +- title: string | ILocalizedString; +- category?: string | ILocalizedString; +-} +- +-export interface IConfigurationProperty { +- description: string; +- type: string | string[]; +- default?: any; ++ /** ++ * Identifier of the command to execute ++ */ ++ readonly command: string; ++ /** ++ * Title by which the command is represented in the UI ++ */ ++ readonly title: string | ILocalizedString; ++ readonly shortTitle?: string; ++ /** ++ * (Optional) Category string by which the command is grouped in the UI ++ */ ++ readonly category?: string | ILocalizedString; ++ /** ++ * (Optional) Condition which must be true to enable the command in the UI (menu and keybindings). Does not prevent executing the command by other means, like the `executeCommand`-api. ++ */ ++ readonly enablement?: string; ++ /** ++ * (Optional) Icon which is used to represent the command in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `\$(zap)` ++ */ ++ readonly icon?: ++ | string ++ | { ++ /** ++ * Icon path when a light theme is used ++ */ ++ readonly light?: string; ++ /** ++ * Icon path when a dark theme is used ++ */ ++ readonly dark?: string; ++ }; + } + + export interface IConfiguration { +- id?: string; +- order?: number; +- title?: string; +- properties: { [key: string]: IConfigurationProperty }; ++ /** ++ * A title for the current category of settings. This label will be rendered in the Settings editor as a subheading. If the title is the same as the extension display name, then the category will be grouped under the main extension heading. ++ */ ++ readonly title?: string; ++ /** ++ * When specified, gives the order of this category of settings relative to other categories. ++ */ ++ readonly order?: number; ++ /** ++ * Description of the configuration properties. ++ */ ++ readonly properties: { [key: string]: IJSONSchema }; + } + + export interface IDebugger { +- label?: string; +- type: string; +- runtime?: string; ++ /** ++ * Unique identifier for this debug adapter. ++ */ ++ readonly type: string; ++ /** ++ * Display name for this debug adapter. ++ */ ++ readonly label?: string; ++ /** ++ * Path to the debug adapter program. Path is either absolute or relative to the extension folder. ++ */ ++ readonly program?: string; ++ /** ++ * Optional arguments to pass to the adapter. ++ */ ++ readonly args?: unknown[]; ++ /** ++ * Optional runtime in case the program attribute is not an executable but requires a runtime. ++ */ ++ readonly runtime?: string; ++ /** ++ * Optional runtime arguments. ++ */ ++ readonly runtimeArgs?: unknown[]; ++ /** ++ * Mapping from interactive variables (e.g. ${action.pickProcess}) in `launch.json` to a command. ++ */ ++ readonly variables?: {}; ++ /** ++ * Configurations for generating the initial 'launch.json'. ++ */ ++ readonly initialConfigurations?: unknown[] | string; ++ /** ++ * List of languages for which the debug extension could be considered the "default debugger". ++ */ ++ readonly languages?: unknown[]; ++ /** ++ * Snippets for adding new configurations in 'launch.json'. ++ */ ++ readonly configurationSnippets?: unknown[]; ++ /** ++ * JSON schema configurations for validating 'launch.json'. ++ */ ++ readonly configurationAttributes?: {}; ++ /** ++ * Condition which must be true to enable this type of debugger. Consider using 'shellExecutionSupported', 'virtualWorkspace', 'resourceScheme' or an extension-defined context key as appropriate for this. ++ */ ++ readonly when?: string; ++ /** ++ * When this condition is true, this debugger type is hidden from the debugger list, but is still enabled. ++ */ ++ readonly hiddenWhen?: string; ++ /** ++ * Optional message to mark this debug type as being deprecated. ++ */ ++ readonly deprecated?: string; ++ /** ++ * Windows specific settings. ++ */ ++ readonly windows?: { ++ /** ++ * Runtime used for Windows. ++ */ ++ runtime?: string; ++ }; ++ /** ++ * macOS specific settings. ++ */ ++ readonly osx?: { ++ /** ++ * Runtime used for macOS. ++ */ ++ runtime?: string; ++ }; ++ /** ++ * Linux specific settings. ++ */ ++ readonly linux?: { ++ /** ++ * Runtime used for Linux. ++ */ ++ readonly runtime?: string; ++ }; ++ /** ++ * UI strings contributed by this debug adapter. ++ */ ++ readonly strings?: { ++ /** ++ * When there are unverified breakpoints in a language supported by this debug adapter, this message will appear on the breakpoint hover and in the breakpoints view. Markdown and command links are supported. ++ */ ++ readonly unverifiedBreakpoints?: string; ++ }; + } + + export interface IGrammar { +- language: string; ++ /** ++ * Language identifier for which this syntax is contributed to. ++ */ ++ readonly language: string; ++ /** ++ * Textmate scope name used by the tmLanguage file. ++ */ ++ readonly scopeName: string; ++ /** ++ * Path of the tmLanguage file. The path is relative to the extension folder and typically starts with './syntaxes/'. ++ */ ++ readonly path: string; ++ /** ++ * A map of scope name to language id if this grammar contains embedded languages. ++ */ ++ readonly embeddedLanguages?: {}; ++ /** ++ * A map of scope name to token types. ++ */ ++ readonly tokenTypes?: { ++ [k: string]: 'string' | 'comment' | 'other'; ++ }; ++ /** ++ * List of language scope names to which this grammar is injected to. ++ */ ++ readonly injectTo?: string[]; ++ /** ++ * Defines which scope names contain balanced brackets. ++ */ ++ readonly balancedBracketScopes?: string[]; ++ /** ++ * Defines which scope names do not contain balanced brackets. ++ */ ++ readonly unbalancedBracketScopes?: string[]; + } + + export interface IJSONValidation { +- fileMatch: string | string[]; +- url: string; ++ /** ++ * The file pattern (or an array of patterns) to match, for example "package.json" or "*.launch". Exclusion patterns start with '!' ++ */ ++ readonly fileMatch?: string | string[]; ++ /** ++ * A schema URL ('http:', 'https:') or relative path to the extension folder ('./'). ++ */ ++ readonly url: string; + } + + export interface IKeyBinding { +- command: string; +- key: string; +- when?: string; +- mac?: string; +- linux?: string; +- win?: string; ++ /** ++ * Identifier of the command to run when keybinding is triggered. ++ */ ++ readonly command: string; ++ /** ++ * Arguments to pass to the command to execute. ++ */ ++ readonly args?: { ++ [k: string]: unknown; ++ }; ++ /** ++ * Key or key sequence (separate keys with plus-sign and sequences with space, e.g. Ctrl+O and Ctrl+L L for a chord). ++ */ ++ readonly key: string; ++ /** ++ * Mac specific key or key sequence. ++ */ ++ readonly mac?: string; ++ /** ++ * Linux specific key or key sequence. ++ */ ++ readonly linux?: string; ++ /** ++ * Windows specific key or key sequence. ++ */ ++ readonly win?: string; ++ /** ++ * Condition when the key is active. ++ */ ++ readonly when?: string; + } + + export interface ILanguage { +- id: string; +- extensions: string[]; +- aliases: string[]; ++ /** ++ * ID of the language. ++ */ ++ readonly id: string; ++ /** ++ * Name aliases for the language. ++ */ ++ readonly aliases?: string[]; ++ /** ++ * File extensions associated to the language. ++ */ ++ readonly extensions?: string[]; ++ /** ++ * File names associated to the language. ++ */ ++ readonly filenames?: string[]; ++ /** ++ * File name glob patterns associated to the language. ++ */ ++ readonly filenamePatterns?: string[]; ++ /** ++ * Mime types associated to the language. ++ */ ++ readonly mimetypes?: string[]; ++ /** ++ * A regular expression matching the first line of a file of the language. ++ */ ++ readonly firstLine?: string; ++ /** ++ * A relative path to a file containing configuration options for the language. ++ */ ++ readonly configuration?: string; ++ /** ++ * A icon to use as file icon, if no icon theme provides one for the language. ++ */ ++ readonly icon?: { ++ /** ++ * Icon path when a light theme is used ++ */ ++ readonly light?: string; ++ /** ++ * Icon path when a dark theme is used ++ */ ++ readonly dark?: string; ++ }; + } + + export interface IMenu { +- command: string; +- alt?: string; +- when?: string; +- group?: string; ++ /** ++ * Identifier of the command to execute. The command must be declared in the 'commands'-section ++ */ ++ readonly command: string; ++ /** ++ * Identifier of an alternative command to execute. The command must be declared in the 'commands'-section ++ */ ++ readonly alt?: string; ++ /** ++ * Condition which must be true to show this item ++ */ ++ readonly when?: string; ++ /** ++ * Group into which this item belongs ++ */ ++ readonly group?: string; ++} ++ ++export interface ISubMenu { ++ /** ++ * Identifier of the submenu to display in this item. ++ */ ++ readonly submenu: string; ++ /** ++ * Condition which must be true to show this item ++ */ ++ readonly when?: string; ++ /** ++ * Group into which this item belongs ++ */ ++ readonly group?: string; + } + + export interface ISnippet { +- language: string; ++ /** ++ * Language identifier for which this snippet is contributed to. ++ */ ++ readonly language: string; ++ /** ++ * Path of the snippets file. The path is relative to the extension folder and typically starts with './snippets/'. ++ */ ++ readonly path: string; ++} ++ ++export interface IColorTheme { ++ /** ++ * Id of the color theme as used in the user settings. ++ */ ++ readonly id: string; ++ /** ++ * Label of the color theme as shown in the UI. ++ */ ++ readonly label: string; ++ /** ++ * Base theme defining the colors around the editor: 'vs' is the light color theme, 'vs-dark' is the dark color theme. 'hc-black' is the dark high contrast theme, 'hc-light' is the light high contrast theme. ++ */ ++ readonly uiTheme: 'vs' | 'vs-dark' | 'hc-black' | 'hc-light'; ++ /** ++ * Path of the tmTheme file. The path is relative to the extension folder and is typically './colorthemes/awesome-color-theme.json'. ++ */ ++ readonly path: string; ++} ++ ++export interface IIconTheme { ++ /** ++ * Id of the file icon theme as used in the user settings. ++ */ ++ readonly id: string; ++ /** ++ * Label of the file icon theme as shown in the UI. ++ */ ++ readonly label: string; ++ /** ++ * Path of the file icon theme definition file. The path is relative to the extension folder and is typically './fileicons/awesome-icon-theme.json'. ++ */ ++ readonly path: string; + } + +-export interface ITheme { +- label: string; ++export interface IProductTheme { ++ /** ++ * Id of the product icon theme as used in the user settings. ++ */ ++ readonly id: string; ++ /** ++ * Label of the product icon theme as shown in the UI. ++ */ ++ readonly label: string; ++ /** ++ * Path of the product icon theme definition file. The path is relative to the extension folder and is typically './producticons/awesome-product-icon-theme.json'. ++ */ ++ readonly path: string; + } + + export interface IViewContainer { +- id: string; +- title: string; ++ /** ++ * Unique id used to identify the container in which views can be contributed using 'views' contribution point ++ */ ++ readonly id: string; ++ /** ++ * Human readable string used to render the container ++ */ ++ readonly title: string; ++ /** ++ * Path to the container icon. Icons are 24x24 centered on a 50x40 block and have a fill color of 'rgb(215, 218, 224)' or '#d7dae0'. It is recommended that icons be in SVG, though any image file type is accepted. ++ */ ++ readonly icon: string; + } + + export interface IView { +- id: string; +- name: string; ++ readonly type?: 'tree' | 'webview'; ++ readonly id: string; ++ /** ++ * The human-readable name of the view. Will be shown ++ */ ++ readonly name: string; ++ /** ++ * Condition which must be true to show this view ++ */ ++ readonly when?: string; ++ /** ++ * Path to the view icon. View icons are displayed when the name of the view cannot be shown. It is recommended that icons be in SVG, though any image file type is accepted. ++ */ ++ readonly icon?: string; ++ /** ++ * Human-readable context for when the view is moved out of its original location. By default, the view's container name will be used. ++ */ ++ readonly contextualTitle?: string; ++ /** ++ * Initial state of the view when the extension is first installed. Once the user has changed the view state by collapsing, moving, or hiding the view, the initial state will not be used again. ++ */ ++ readonly visibility?: 'visible' | 'hidden' | 'collapsed'; ++ /** ++ * The initial size of the view. The size will behave like the css 'flex' property, and will set the initial size when the view is first shown. In the side bar, this is the height of the view. This value is only respected when the same extension owns both the view and the view container. ++ */ ++ readonly initialSize?: number; + } + + export interface IColor { +- id: string; +- description: string; +- defaults: { light: string; dark: string; highContrast: string }; ++ /** ++ * The identifier of the themable color ++ */ ++ readonly id: string; ++ /** ++ * The description of the themable color ++ */ ++ readonly description: string; ++ readonly defaults: { ++ /** ++ * The default color for light themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. ++ */ ++ readonly light: string; ++ /** ++ * The default color for dark themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. ++ */ ++ readonly dark: string; ++ /** ++ * The default color for high contrast dark themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. If not provided, the `dark` color is used as default for high contrast dark themes. ++ */ ++ readonly highContrast?: string; ++ /** ++ * The default color for high contrast light themes. Either a color value in hex (#RRGGBB[AA]) or the identifier of a themable color which provides the default. If not provided, the `light` color is used as default for high contrast light themes. ++ */ ++ readonly highContrastLight?: string; ++ }; + } + + interface IWebviewEditor { + readonly viewType: string; + readonly priority: string; +- readonly selector: readonly { ++ /** ++ * Human readable name of the custom editor. This is displayed to users when selecting which editor to use. ++ */ ++ readonly displayName: string; ++ /** ++ * Set of globs that the custom editor is enabled for. ++ */ ++ readonly selector: { ++ /** ++ * Glob that the custom editor is enabled for. ++ */ + readonly filenamePattern?: string; + }[]; + } + + export interface ICodeActionContributionAction { + readonly kind: string; ++ /** ++ * Label for the code action used in the UI. ++ */ + readonly title: string; ++ /** ++ * Description of what the code action does. ++ */ + readonly description?: string; + } + + export interface ICodeActionContribution { +- readonly languages: readonly string[]; ++ /** ++ * Language modes that the code actions are enabled for. ++ */ ++ readonly languages: string[]; + readonly actions: readonly ICodeActionContributionAction[]; + } + + export interface IAuthenticationContribution { ++ /** ++ * The id of the authentication provider. ++ */ + readonly id: string; ++ /** ++ * The human readable name of the authentication provider. ++ */ + readonly label: string; + } + +-export interface IWalkthroughStep { ++export interface IWalkthroughStep2 { + readonly id: string; + readonly title: string; + readonly description: string | undefined; +@@ -133,14 +520,119 @@ export interface IWalkthroughStep { + readonly when?: string; + } + ++export interface IWalkthroughStep { ++ /** ++ * Unique identifier for this step. This is used to keep track of which steps have been completed. ++ */ ++ readonly id: string; ++ /** ++ * Title of step. ++ */ ++ readonly title: string; ++ /** ++ * Description of step. Supports ``preformatted``, __italic__, and **bold** text. Use markdown-style links for commands or external links: [Title](command:myext.command), [Title](command:toSide:myext.command), or [Title](https://aka.ms). Links on their own line will be rendered as buttons. ++ */ ++ readonly description?: string; ++ readonly button?: { ++ [k: string]: unknown; ++ }; ++ /** ++ * Media to show alongside this step, either an image or markdown content. ++ */ ++ readonly media: { ++ readonly path?: { ++ [k: string]: unknown; ++ }; ++ /** ++ * Path to an image - or object consisting of paths to light, dark, and hc images - relative to extension directory. Depending on context, the image will be displayed from 400px to 800px wide, with similar bounds on height. To support HIDPI displays, the image will be rendered at 1.5x scaling, for example a 900 physical pixels wide image will be displayed as 600 logical pixels wide. ++ */ ++ readonly image: string | { ++ /** ++ * Path to the image for dark themes, relative to extension directory. ++ */ ++ readonly dark: string; ++ /** ++ * Path to the image for light themes, relative to extension directory. ++ */ ++ readonly light: string; ++ /** ++ * Path to the image for hc themes, relative to extension directory. ++ */ ++ readonly hc: string; ++ /** ++ * Path to the image for hc light themes, relative to extension directory. ++ */ ++ readonly hcLight: string; ++ }; ++ /** ++ * Alternate text to display when the image cannot be loaded or in screen readers. ++ */ ++ readonly altText: string; ++ readonly markdown?: never; ++ readonly svg?: never; ++ } | { ++ /** ++ * Path to an svg, color tokens are supported in variables to support theming to match the workbench. ++ */ ++ readonly svg: string; ++ /** ++ * Alternate text to display when the image cannot be loaded or in screen readers. ++ */ ++ readonly altText: string; ++ readonly image?: never; ++ readonly markdown?: never; ++ } | { ++ readonly path?: { ++ [k: string]: unknown; ++ }; ++ /** ++ * Path to the markdown document, relative to extension directory. ++ */ ++ readonly markdown: string; ++ readonly image?: never; ++ readonly svg?: never; ++ }; ++ /** ++ * Events that should trigger this step to become checked off. If empty or not defined, the step will check off when any of the step's buttons or links are clicked; if the step has no buttons or links it will check on when it is selected. ++ */ ++ readonly completionEvents?: string[]; ++ /** ++ * Signal to mark step as complete. ++ * @deprecated use `completionEvents: 'onCommand:...'` ++ **/ ++ readonly doneOn?: { command: string }; ++ /** ++ * Context key expression to control the visibility of this step. ++ */ ++ readonly when?: string; ++} ++ + export interface IWalkthrough { ++ /** ++ * Unique identifier for this walkthrough. ++ */ + readonly id: string; ++ /** ++ * Title of walkthrough. ++ */ + readonly title: string; ++ /** ++ * Relative path to the icon of the walkthrough. The path is relative to the extension location. If not specified, the icon defaults to the extension icon if available. ++ */ + readonly icon?: string; ++ /** ++ * Description of walkthrough. ++ */ + readonly description: string; +- readonly steps: IWalkthroughStep[]; +- readonly featuredFor: string[] | undefined; ++ /** ++ * Walkthroughs that match one of these glob patterns appear as 'featured' in workspaces with the specified files. For example, a walkthrough for TypeScript projects might specify `tsconfig.json` here. ++ */ ++ readonly featuredFor?: string[]; ++ /** ++ * Context key expression to control the visibility of this walkthrough. ++ */ + readonly when?: string; ++ readonly steps: IWalkthroughStep[]; + } + + export interface IStartEntry { +@@ -152,14 +644,53 @@ export interface IStartEntry { + } + + export interface INotebookEntry { ++ /** ++ * Type of the notebook. ++ */ + readonly type: string; ++ /** ++ * Human readable name of the notebook. ++ */ + readonly displayName: string; ++ /** ++ * Set of globs that the notebook is for. ++ */ ++ readonly selector: { ++ /** ++ * Glob that the notebook is enabled for. ++ */ ++ readonly filenamePattern?: string; ++ /** ++ * Glob that the notebook is disabled for. ++ */ ++ readonly excludeFileNamePattern?: string; ++ }[]; ++ readonly priority?: 'default' | 'option'; + } + + export interface INotebookRendererContribution { ++ /** ++ * Unique identifier of the notebook output renderer. ++ */ + readonly id: string; ++ /** ++ * Human readable name of the notebook output renderer. ++ */ + readonly displayName: string; ++ readonly dependencies?: string[]; ++ readonly optionalDependencies?: string[]; ++ /** ++ * Defines how and if the renderer needs to communicate with an extension host, via `createRendererMessaging`. Renderers with stronger messaging requirements may not work in all environments. ++ */ ++ readonly requiresMessaging?: 'always' | 'optional' | 'never'; ++ /** ++ * Set of globs that the notebook is for. ++ */ + readonly mimeTypes: string[]; ++ readonly entrypoint: string | { ++ readonly extends: string; ++ readonly path: string; ++ }; + } + + export interface IDebugVisualizationContribution { +@@ -168,43 +699,560 @@ export interface IDebugVisualizationContribution { + } + + export interface ITranslation { +- id: string; +- path: string; ++ /** ++ * Id of VS Code or Extension for which this translation is contributed to. Id of VS Code is always `vscode` and of extension should be in format `publisherId.extensionName`. ++ */ ++ readonly id: string; ++ /** ++ * A relative path to a file containing translations for the language. ++ */ ++ readonly path: string; + } + + export interface ILocalizationContribution { +- languageId: string; +- languageName?: string; +- localizedLanguageName?: string; +- translations: ITranslation[]; +- minimalTranslations?: { [key: string]: string }; ++ /** ++ * Id of the language into which the display strings are translated. ++ */ ++ readonly languageId: string; ++ /** ++ * Name of the language in English. ++ */ ++ readonly languageName?: string; ++ /** ++ * Name of the language in contributed language. ++ */ ++ readonly localizedLanguageName?: string; ++ /** ++ * ++ */ ++ readonly translations: ITranslation[]; ++} ++ ++export interface ITerminal { ++ readonly profiles?: { ++ readonly id: string; ++ readonly title: string; ++ readonly icon?: (string | { ++ /** ++ * Icon path when a light theme is used ++ */ ++ readonly light?: string; ++ /** ++ * Icon path when a dark theme is used ++ */ ++ readonly dark?: string; ++ [k: string]: unknown; ++ }); ++ }[]; ++} ++ ++export interface IStatusBarItem { ++ readonly id: string; ++ /** ++ * The name of the entry, like 'Python Language Indicator', 'Git Status' etc. Try to keep the length of the name short, yet descriptive enough that users can understand what the status bar item is about. ++ */ ++ readonly name: string; ++ /** ++ * The text to show for the entry. You can embed icons in the text by leveraging the `$()`-syntax, like 'Hello $(globe)!' ++ */ ++ readonly text: string; ++ /** ++ * The tooltip text for the entry. ++ */ ++ readonly tooltip?: string; ++ /** ++ * The command to execute when the status bar entry is clicked. ++ */ ++ readonly command?: string; ++ /** ++ * The alignment of the status bar entry. ++ */ ++ readonly alignment: 'left' | 'right'; ++ /** ++ * The priority of the status bar entry. Higher value means the item should be shown more to the left. ++ */ ++ readonly priority?: number; ++ /** ++ * Defines the role and aria label to be used when the status bar entry is focused. ++ */ ++ readonly accessibilityInformation?: { ++ /** ++ * The role of the status bar entry which defines how a screen reader interacts with it. More about aria roles can be found here https://w3c.github.io/aria/#widget_roles ++ */ ++ readonly role?: string; ++ /** ++ * The aria label of the status bar entry. Defaults to the entry's text. ++ */ ++ readonly label?: string; ++ }; ++} ++ ++export interface IRemoteHelp { ++ /** ++ * The url, or a command that returns the url, to your project's Getting Started page, or a walkthrough ID contributed by your project's extension ++ */ ++ readonly getStarted?: string | { ++ /** ++ * The ID of a Get Started walkthrough to open. ++ */ ++ id: string; ++ }; ++ /** ++ * The url, or a command that returns the url, to your project's documentation page ++ */ ++ readonly documentation?: string; ++ /** ++ * The url, or a command that returns the url, to your project's feedback reporter ++ */ ++ readonly feedback?: string; ++ /** ++ * The url, or a command that returns the url, to your project's issue reporter ++ */ ++ readonly reportIssue?: string; ++ /** ++ * The url, or a command that returns the url, to your project's issues list ++ */ ++ readonly issues?: string; ++} ++ ++export interface ITaskDefinitions { ++ /** ++ * The actual task type. Please note that types starting with a '$' are reserved for internal usage. ++ */ ++ readonly type?: string; ++ readonly required?: string[]; ++ /** ++ * Additional properties of the task type ++ */ ++ readonly properties?: { ++ [k: string]: IJSONSchema; ++ }; ++ readonly when?: string; ++} ++ ++export interface IIcon { ++ /** ++ * The description of the themable icon ++ */ ++ readonly description: string; ++ /** ++ * The default of the icon. Either a reference to an extisting ThemeIcon or an icon in an icon font. ++ */ ++ readonly default: string | { ++ /** ++ * The path of the icon font that defines the icon. ++ */ ++ readonly fontPath: string; ++ /** ++ * The character for the icon in the icon font. ++ */ ++ readonly fontCharacter: string; ++ }; ++} ++ ++export interface IDocumentationRefactoring { ++ /** ++ * Label for the documentation used in the UI. ++ */ ++ readonly title: string; ++ /** ++ * When clause. ++ */ ++ readonly when: string; ++ /** ++ * Command executed. ++ */ ++ readonly command: string; ++} ++ ++export interface IDocumentation { ++ /** ++ * Contributed documentation for refactorings. ++ */ ++ readonly refactoring?: IDocumentationRefactoring[]; ++} ++ ++export interface ISubMenu { ++ /** ++ * Identifier of the menu to display as a submenu. ++ */ ++ readonly id: string; ++ /** ++ * The label of the menu item which leads to this submenu. ++ */ ++ readonly label: string; ++ /** ++ * (Optional) Icon which is used to represent the submenu in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `\$(zap)` ++ */ ++ readonly icon?: ++ | string ++ | { ++ /** ++ * Icon path when a light theme is used ++ */ ++ readonly light?: string; ++ /** ++ * Icon path when a dark theme is used ++ */ ++ readonly dark?: string; ++ }; ++} ++ ++interface IResourceLabelFormatters { ++ /** ++ * URI scheme on which to match the formatter on. For example "file". Simple glob patterns are supported. ++ */ ++ readonly scheme: string; ++ /** ++ * URI authority on which to match the formatter on. Simple glob patterns are supported. ++ */ ++ readonly authority?: string; ++ /** ++ * Rules for formatting uri resource labels. ++ */ ++ readonly formatting: { ++ /** ++ * Label rules to display. For example: myLabel:/${path}. ${path}, ${scheme}, ${authority} and ${authoritySuffix} are supported as variables. ++ */ ++ readonly label?: string; ++ /** ++ * Separator to be used in the uri label display. '/' or '' as an example. ++ */ ++ readonly separator?: string; ++ /** ++ * Controls whether `${path}` substitutions should have starting separator characters stripped. ++ */ ++ readonly stripPathStartingSeparator?: boolean; ++ /** ++ * Controls if the start of the uri label should be tildified when possible. ++ */ ++ readonly tildify?: boolean; ++ /** ++ * Suffix appended to the workspace label. ++ */ ++ readonly workspaceSuffix?: string; ++ }; ++} ++ ++export interface ISemanticTokenTypes { ++ /** ++ * The identifier of the semantic token type ++ */ ++ readonly id?: string; ++ /** ++ * The super type of the semantic token type ++ */ ++ readonly superType?: string; ++ /** ++ * The description of the semantic token type ++ */ ++ readonly description?: string; ++} ++ ++export interface ISemanticTokenModifiers { ++ /** ++ * The identifier of the semantic token modifier ++ */ ++ readonly id?: string; ++ /** ++ * The description of the semantic token modifier ++ */ ++ readonly description?: string; ++} ++ ++export interface ISemanticTokenScopes { ++ /** ++ * Lists the languge for which the defaults are. ++ */ ++ readonly language?: string; ++ /** ++ * Maps a semantic token (described by semantic token selector) to one or more textMate scopes used to represent that token. ++ */ ++ readonly scopes?: { ++ [k: string]: string[]; ++ }; ++} ++ ++export interface IBreakpoint { ++ /** ++ * Allow breakpoints for this language. ++ */ ++ readonly language?: string; ++ /** ++ * Condition which must be true to enable breakpoints in this language. Consider matching this to the debugger when clause as appropriate. ++ */ ++ readonly when?: string; ++} ++ ++export interface ITerminalQuickFix { ++ /** ++ * The ID of the quick fix provider ++ */ ++ readonly id: string; ++ /** ++ * A regular expression or string to test the command line against ++ */ ++ readonly commandLineMatcher: string; ++ readonly outputMatcher: { ++ /** ++ * A regular expression or string to test the command line against ++ */ ++ readonly lineMatcher: string; ++ /** ++ * Where the search should begin in the buffer ++ */ ++ readonly anchor: 'top' | 'bottom'; ++ /** ++ * The number of lines vertically from the anchor in the buffer to start matching against ++ */ ++ readonly offset: number; ++ /** ++ * The number of rows to match against, this should be as small as possible for performance reasons ++ */ ++ readonly length: number; ++ }; ++ /** ++ * The command exit result to match on ++ */ ++ readonly commandExitResult: 'success' | 'error'; ++ /** ++ * The kind of the resulting quick fix. This changes how the quick fix is presented. Defaults to `"fix"`. ++ */ ++ readonly kind?: 'default' | 'explain'; ++} ++ ++export interface IInteractiveSession { ++ /** ++ * Unique identifier for this Interactive Session provider. ++ */ ++ readonly id: string; ++ /** ++ * Display name for this Interactive Session provider. ++ */ ++ readonly label: string; ++ /** ++ * An icon for this Interactive Session provider. ++ */ ++ readonly icon?: string; ++ /** ++ * A condition which must be true to enable this Interactive Session provider. ++ */ ++ readonly when?: string; ++} ++ ++export interface INotebook { ++ /** ++ * Type of the notebook. ++ */ ++ readonly type: string; ++ /** ++ * Human readable name of the notebook. ++ */ ++ readonly displayName: string; ++ /** ++ * Set of globs that the notebook is for. ++ */ ++ readonly selector: { ++ /** ++ * Glob that the notebook is enabled for. ++ */ ++ readonly filenamePattern?: string; ++ /** ++ * Glob that the notebook is disabled for. ++ */ ++ readonly excludeFileNamePattern?: string; ++ }[]; ++ readonly priority?: 'default' | 'option'; ++} ++ ++export interface NotebookPreload { ++ /** ++ * Type of the notebook. ++ */ ++ readonly type: string; ++ /** ++ * Path to file loaded in the webview. ++ */ ++ readonly entrypoint: string; ++ /** ++ * Paths to additional resources that should be allowed in the webview. ++ */ ++ readonly localResourceRoots?: string[]; ++} ++ ++export interface IViewsWelcome { ++ readonly view: string; ++ /** ++ * Welcome content to be displayed. The format of the contents is a subset of Markdown, with support for links only. ++ */ ++ readonly contents: string; ++ /** ++ * Condition when the welcome content should be displayed. ++ */ ++ readonly when?: string; ++ /** ++ * Group to which this welcome content belongs. Proposed API. ++ */ ++ readonly group?: string; ++ /** ++ * Condition when the welcome content buttons and command links should be enabled. ++ */ ++ readonly enablement?: string; + } + + export interface IExtensionContributions { +- commands?: ICommand[]; +- configuration?: IConfiguration | IConfiguration[]; +- debuggers?: IDebugger[]; +- grammars?: IGrammar[]; +- jsonValidation?: IJSONValidation[]; +- keybindings?: IKeyBinding[]; +- languages?: ILanguage[]; +- menus?: { [context: string]: IMenu[] }; +- snippets?: ISnippet[]; +- themes?: ITheme[]; +- iconThemes?: ITheme[]; +- productIconThemes?: ITheme[]; +- viewsContainers?: { [location: string]: IViewContainer[] }; +- views?: { [location: string]: IView[] }; +- colors?: IColor[]; +- localizations?: ILocalizationContribution[]; ++ /** ++ * Contributes terminal functionality. ++ */ ++ readonly terminal?: ITerminal; ++ /** ++ * Contributes commands to the command palette. ++ */ ++ readonly commands?: ICommand[]; ++ /** ++ * Contributes configuration settings. ++ */ ++ readonly configuration?: IConfiguration | IConfiguration[]; ++ /** ++ * Contributes debug adapters. ++ */ ++ readonly debuggers?: IDebugger[]; ++ /** ++ * Contributes breakpoints. ++ */ ++ readonly breakpoints?: IBreakpoint[]; ++ /** ++ * Contributes textmate tokenizers. ++ */ ++ readonly grammars?: IGrammar[]; ++ /** ++ * Contributes json schema configuration. ++ */ ++ readonly jsonValidation?: IJSONValidation[]; ++ /** ++ * Contributes keybindings. ++ */ ++ readonly keybindings?: IKeyBinding[]; ++ /** ++ * Contributes language declarations. ++ */ ++ readonly languages?: ILanguage[]; ++ /** ++ * Contributes menu items to the editor ++ */ ++ readonly menus?: { [context: string]: IMenu[] }; ++ /** ++ * Contributes submenu items to the editor ++ */ ++ readonly submenus?: ISubMenu[]; ++ /** ++ * Contributes snippets. ++ */ ++ readonly snippets?: ISnippet[]; ++ /** ++ * Contributes textmate color themes. ++ */ ++ readonly themes?: IColorTheme[]; ++ /** ++ * Contributes file icon themes. ++ */ ++ readonly iconThemes?: IIconTheme[]; ++ /** ++ * Contributes product icon themes. ++ */ ++ readonly productIconThemes?: IProductTheme[]; ++ /** ++ * Contributes views containers to the editor ++ */ ++ readonly viewsContainers?: { [location: string]: IViewContainer[] }; ++ /** ++ * Contributes views to the editor ++ */ ++ readonly views?: { [location: string]: IView[] }; ++ /** ++ * Contributes extension defined themable colors ++ */ ++ readonly colors?: IColor[]; ++ /** ++ * Contributes localizations to the editor ++ */ ++ readonly localizations?: ILocalizationContribution[]; ++ /** ++ * Contributed custom editors. ++ */ + readonly customEditors?: readonly IWebviewEditor[]; + readonly codeActions?: readonly ICodeActionContribution[]; +- authentication?: IAuthenticationContribution[]; +- walkthroughs?: IWalkthrough[]; +- startEntries?: IStartEntry[]; ++ /** ++ * Contributes authentication ++ */ ++ readonly authentication?: IAuthenticationContribution[]; ++ /** ++ * Contribute walkthroughs to help users getting started with your extension. ++ */ ++ readonly walkthroughs?: IWalkthrough[]; ++ readonly startEntries?: IStartEntry[]; ++ /** ++ * Contributes notebook document provider. ++ */ + readonly notebooks?: INotebookEntry[]; ++ /** ++ * Contributes notebook output renderer provider. ++ */ + readonly notebookRenderer?: INotebookRendererContribution[]; + readonly debugVisualizers?: IDebugVisualizationContribution[]; ++ /** ++ * Contributes notebook preloads. ++ */ ++ readonly notebookPreload?: NotebookPreload[]; ++ /** ++ * Contributes items to the status bar. ++ */ ++ readonly statusBarItems?: IStatusBarItem[]; ++ /** ++ * Contributes help information for Remote ++ */ ++ readonly remoteHelp?: IRemoteHelp; ++ /** ++ * Contributes task kinds ++ */ ++ readonly taskDefinitions?: ITaskDefinitions[]; ++ /** ++ * Contributes extension defined themable icons ++ */ ++ readonly icons?: { [id: string]: IIcon }; ++ /** ++ * Contributed documentation. ++ */ ++ readonly documentation?: IDocumentation; ++ /** ++ * Contributes resource label formatting rules. ++ */ ++ readonly resourceLabelFormatters?: IResourceLabelFormatters[]; ++ readonly configurationDefaults?: { [id: string]: any }; ++ /** ++ * Contributes semantic token types. ++ */ ++ readonly semanticTokenTypes?: ISemanticTokenTypes[]; ++ /** ++ * Contributes semantic token modifiers. ++ */ ++ readonly semanticTokenModifiers?: ISemanticTokenModifiers[]; ++ /** ++ * Contributes semantic token scope maps. ++ */ ++ readonly semanticTokenScopes?: ISemanticTokenScopes[]; ++ /** ++ * Contributes terminal quick fixes. ++ */ ++ readonly terminalQuickFixes?: ITerminalQuickFix[]; ++ /** ++ * Contributes an Interactive Session provider ++ */ ++ readonly interactiveSession?: IInteractiveSession[]; ++ /** ++ * Contributed views welcome content. Welcome content will be rendered in tree based views whenever they have no meaningful content to display, ie. the File Explorer when no folder is open. Such content is useful as in-product documentation to drive users to use certain features before they are available. A good example would be a `Clone Repository` button in the File Explorer welcome view. ++ */ ++ readonly viewsWelcome?: IViewsWelcome[]; + } + + export interface IExtensionCapabilities { +diff --git a/src/vs/workbench/services/search/common/queryBuilder.ts b/src/vs/workbench/services/search/common/queryBuilder.ts +index 9124249957a..057b9a21ea2 100644 +--- a/src/vs/workbench/services/search/common/queryBuilder.ts ++++ b/src/vs/workbench/services/search/common/queryBuilder.ts +@@ -545,10 +545,10 @@ export class QueryBuilder { + folderName: includeFolderName ? folderName : undefined, + excludePattern: Object.keys(excludePattern).length > 0 ? excludePattern : undefined, + fileEncoding: folderConfig.files && folderConfig.files.encoding, +- disregardIgnoreFiles: typeof options.disregardIgnoreFiles === 'boolean' ? options.disregardIgnoreFiles : !folderConfig.search.useIgnoreFiles, +- disregardGlobalIgnoreFiles: typeof options.disregardGlobalIgnoreFiles === 'boolean' ? options.disregardGlobalIgnoreFiles : !folderConfig.search.useGlobalIgnoreFiles, +- disregardParentIgnoreFiles: typeof options.disregardParentIgnoreFiles === 'boolean' ? options.disregardParentIgnoreFiles : !folderConfig.search.useParentIgnoreFiles, +- ignoreSymlinks: typeof options.ignoreSymlinks === 'boolean' ? options.ignoreSymlinks : !folderConfig.search.followSymlinks, ++ disregardIgnoreFiles: typeof options.disregardIgnoreFiles === 'boolean' ? options.disregardIgnoreFiles : !folderConfig.search?.useIgnoreFiles, ++ disregardGlobalIgnoreFiles: typeof options.disregardGlobalIgnoreFiles === 'boolean' ? options.disregardGlobalIgnoreFiles : !folderConfig.search?.useGlobalIgnoreFiles, ++ disregardParentIgnoreFiles: typeof options.disregardParentIgnoreFiles === 'boolean' ? options.disregardParentIgnoreFiles : !folderConfig.search?.useParentIgnoreFiles, ++ ignoreSymlinks: typeof options.ignoreSymlinks === 'boolean' ? options.ignoreSymlinks : !folderConfig.search?.followSymlinks, + }; + } + } +diff --git a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts +index 9a7bf4aa503..235e0ed2948 100644 +--- a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts ++++ b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts +@@ -186,7 +186,7 @@ class ColorDataRenderer extends Disposable implements IExtensionFeatureTableRend + color.description, + toColor(color.defaults.dark) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.dark}\``), + toColor(color.defaults.light) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.light}\``), +- toColor(color.defaults.highContrast) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.highContrast}\``), ++ toColor(color.defaults.highContrast!) ?? new MarkdownString().appendMarkdown(`\`${color.defaults.highContrast}\``), + ]; + }); + +diff --git a/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts b/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts +index 80f5ee077cb..49abd845677 100644 +--- a/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts ++++ b/src/vs/workbench/services/themes/common/tokenClassificationExtensionPoint.ts +@@ -69,6 +69,7 @@ const tokenModifierExtPoint = ExtensionsRegistry.registerExtensionPoint +Date: Mon, 11 Mar 2024 17:41:13 +0100 +Subject: [PATCH 28/58] fix: fix dependency injection + +--- + src/vs/platform/instantiation/common/instantiationService.ts | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/vs/platform/instantiation/common/instantiationService.ts b/src/vs/platform/instantiation/common/instantiationService.ts +index ef9ae6601ce..6182c4881a6 100644 +--- a/src/vs/platform/instantiation/common/instantiationService.ts ++++ b/src/vs/platform/instantiation/common/instantiationService.ts +@@ -195,8 +195,10 @@ export class InstantiationService implements IInstantiationService { + + if (instanceOrDesc instanceof SyncDescriptor) { + const d = { id: dependency.id, desc: instanceOrDesc, _trace: item._trace.branch(dependency.id, true) }; ++ if (!graph.lookup(d)) { ++ stack.push(d); ++ } + graph.insertEdge(item, d); +- stack.push(d); + } + } + } +-- +2.34.1 + diff --git a/vscode-paches/0029-fix-only-run-some-code-if-inside-the-worker.patch b/vscode-paches/0029-fix-only-run-some-code-if-inside-the-worker.patch new file mode 100644 index 00000000..0766c8fb --- /dev/null +++ b/vscode-paches/0029-fix-only-run-some-code-if-inside-the-worker.patch @@ -0,0 +1,103 @@ +From bf65674987d4be98b1608be74adda73970cfaf53 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:42:28 +0100 +Subject: [PATCH 29/58] fix: only run some code if inside the worker + +--- + .../workbench/api/common/extHostExtensionService.ts | 10 ++++++---- + src/vs/workbench/api/common/extensionHostMain.ts | 11 ++++++++--- + .../workbench/api/worker/extHostExtensionService.ts | 7 +++++-- + 3 files changed, 19 insertions(+), 9 deletions(-) + +diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts +index 91f910aa4c8..4660b516306 100644 +--- a/src/vs/workbench/api/common/extHostExtensionService.ts ++++ b/src/vs/workbench/api/common/extHostExtensionService.ts +@@ -44,7 +44,7 @@ import { Schemas } from 'vs/base/common/network'; + import { IResolveAuthorityResult } from 'vs/workbench/services/extensions/common/extensionHostProxy'; + import { IExtHostLocalizationService } from 'vs/workbench/api/common/extHostLocalizationService'; + import { StopWatch } from 'vs/base/common/stopwatch'; +-import { isCI, setTimeout0 } from 'vs/base/common/platform'; ++import { isWebWorker, isCI, setTimeout0 } from 'vs/base/common/platform'; + import { IExtHostManagedSockets } from 'vs/workbench/api/common/extHostManagedSockets'; + import { Dto } from 'vs/workbench/services/extensions/common/proxyIdentifier'; + +@@ -256,9 +256,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme + this._extHostTerminalService.dispose(); + this._activator.dispose(); + +- errors.setUnexpectedErrorHandler((err) => { +- this._logService.error(err); +- }); ++ if (isWebWorker) { ++ errors.setUnexpectedErrorHandler((err) => { ++ this._logService.error(err); ++ }); ++ } + + // Invalidate all proxies + this._extHostContext.dispose(); +diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts +index f1c84b938a2..c0a5c4643be 100644 +--- a/src/vs/workbench/api/common/extensionHostMain.ts ++++ b/src/vs/workbench/api/common/extensionHostMain.ts +@@ -23,6 +23,7 @@ import { IURITransformerService, URITransformerService } from 'vs/workbench/api/ + import { IExtHostExtensionService, IHostUtils } from 'vs/workbench/api/common/extHostExtensionService'; + import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry'; + import { Mutable } from 'vs/base/common/types'; ++import { isWebWorker } from 'vs/base/common/platform'; + + export interface IExitFn { + (code?: number): any; +@@ -161,7 +162,9 @@ export class ExtensionHostMain { + + const instaService: IInstantiationService = new InstantiationService(services, true); + +- instaService.invokeFunction(ErrorHandler.installEarlyHandler); ++ if (isWebWorker) { ++ instaService.invokeFunction(ErrorHandler.installEarlyHandler); ++ } + + // ugly self - inject + this._logService = instaService.invokeFunction(accessor => accessor.get(ILogService)); +@@ -180,8 +183,10 @@ export class ExtensionHostMain { + this._extensionService = instaService.invokeFunction(accessor => accessor.get(IExtHostExtensionService)); + this._extensionService.initialize(); + +- // install error handler that is extension-aware +- instaService.invokeFunction(ErrorHandler.installFullHandler); ++ if (isWebWorker) { ++ // install error handler that is extension-aware ++ instaService.invokeFunction(ErrorHandler.installFullHandler); ++ } + } + + async asBrowserUri(uri: URI): Promise { +diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts +index b83a462131d..5ce2ec7413b 100644 +--- a/src/vs/workbench/api/worker/extHostExtensionService.ts ++++ b/src/vs/workbench/api/worker/extHostExtensionService.ts +@@ -12,6 +12,7 @@ import { IExtensionDescription } from 'vs/platform/extensions/common/extensions' + import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes'; + import { timeout } from 'vs/base/common/async'; + import { ExtHostConsoleForwarder } from 'vs/workbench/api/worker/extHostConsoleForwarder'; ++import { isWebWorker } from 'vs/base/common/platform'; + + class WorkerRequireInterceptor extends RequireInterceptor { + +@@ -39,8 +40,10 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { + private _fakeModules?: WorkerRequireInterceptor; + + protected async _beforeAlmostReadyToRunExtensions(): Promise { +- // make sure console.log calls make it to the render +- this._instaService.createInstance(ExtHostConsoleForwarder); ++ if (isWebWorker) { ++ // make sure console.log calls make it to the render ++ this._instaService.createInstance(ExtHostConsoleForwarder); ++ } + + // initialize API and register actors + const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); +-- +2.34.1 + diff --git a/vscode-paches/0030-fix-override-log-services-even-in-main-thread.patch b/vscode-paches/0030-fix-override-log-services-even-in-main-thread.patch new file mode 100644 index 00000000..c64c5283 --- /dev/null +++ b/vscode-paches/0030-fix-override-log-services-even-in-main-thread.patch @@ -0,0 +1,59 @@ +From 108bc5903368d15f9d32cc332d3f8457fb253cc9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:46:45 +0100 +Subject: [PATCH 30/58] fix: override log services even in main thread + +--- + src/vs/workbench/api/common/extensionHostMain.ts | 5 +++++ + src/vs/workbench/api/worker/extHost.worker.services.ts | 4 ---- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts +index c0a5c4643be..af014495458 100644 +--- a/src/vs/workbench/api/common/extensionHostMain.ts ++++ b/src/vs/workbench/api/common/extensionHostMain.ts +@@ -24,6 +24,9 @@ import { IExtHostExtensionService, IHostUtils } from 'vs/workbench/api/common/ex + import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry'; + import { Mutable } from 'vs/base/common/types'; + import { isWebWorker } from 'vs/base/common/platform'; ++import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; ++import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; ++import { ExtHostLoggerService } from 'vs/workbench/api/common/extHostLoggerService'; + + export interface IExitFn { + (code?: number): any; +@@ -159,6 +162,8 @@ export class ExtensionHostMain { + services.set(IExtHostRpcService, new ExtHostRpcService(this._rpcProtocol)); + services.set(IURITransformerService, new URITransformerService(uriTransformer)); + services.set(IHostUtils, hostUtils); ++ services.set(ILogService, new SyncDescriptor(ExtHostLogService, [true], true)); ++ services.set(ILoggerService, new SyncDescriptor(ExtHostLoggerService, [], true)); + + const instaService: IInstantiationService = new InstantiationService(services, true); + +diff --git a/src/vs/workbench/api/worker/extHost.worker.services.ts b/src/vs/workbench/api/worker/extHost.worker.services.ts +index 20ec7e138a6..e284ed6752b 100644 +--- a/src/vs/workbench/api/worker/extHost.worker.services.ts ++++ b/src/vs/workbench/api/worker/extHost.worker.services.ts +@@ -3,11 +3,8 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; + import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; +-import { ILogService } from 'vs/platform/log/common/log'; + import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; +-import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; + import { ExtensionStoragePaths, IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths'; + import { ExtHostExtensionService } from 'vs/workbench/api/worker/extHostExtensionService'; + +@@ -17,6 +14,5 @@ import { ExtHostExtensionService } from 'vs/workbench/api/worker/extHostExtensio + // ### ### + // ######################################################################### + +-registerSingleton(ILogService, new SyncDescriptor(ExtHostLogService, [true], true)); + registerSingleton(IExtHostExtensionService, ExtHostExtensionService, InstantiationType.Eager); + registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths, InstantiationType.Eager); +-- +2.34.1 + diff --git a/vscode-paches/0031-feat-expose-extHostExtensionService.patch b/vscode-paches/0031-feat-expose-extHostExtensionService.patch new file mode 100644 index 00000000..dffd96c4 --- /dev/null +++ b/vscode-paches/0031-feat-expose-extHostExtensionService.patch @@ -0,0 +1,36 @@ +From 0beca3776335cf03ee70b3b0893f04dec63ed2e0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:47:22 +0100 +Subject: [PATCH 31/58] feat: expose extHostExtensionService + +--- + src/vs/workbench/api/common/extensionHostMain.ts | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/vs/workbench/api/common/extensionHostMain.ts b/src/vs/workbench/api/common/extensionHostMain.ts +index af014495458..b1c93afd65f 100644 +--- a/src/vs/workbench/api/common/extensionHostMain.ts ++++ b/src/vs/workbench/api/common/extensionHostMain.ts +@@ -12,7 +12,7 @@ import { MainContext, MainThreadConsoleShape } from 'vs/workbench/api/common/ext + import { IExtensionHostInitData } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; + import { RPCProtocol } from 'vs/workbench/services/extensions/common/rpcProtocol'; + import { ExtensionIdentifier, IExtensionDescription, IRelaxedExtensionDescription } from 'vs/platform/extensions/common/extensions'; +-import { ILogService } from 'vs/platform/log/common/log'; ++import { ILogService, ILoggerService } from 'vs/platform/log/common/log'; + import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; + import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; + import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; +@@ -208,6 +208,10 @@ export class ExtensionHostMain { + this._extensionService.terminate(reason); + } + ++ getExtHostExtensionService(): IExtHostExtensionService { ++ return this._extensionService; ++ } ++ + private static _transform(initData: IExtensionHostInitData, rpcProtocol: RPCProtocol): IExtensionHostInitData { + initData.extensions.allExtensions.forEach((ext) => { + (>ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation)); +-- +2.34.1 + diff --git a/vscode-paches/0032-cleanup-remove-non-ESM-compatible-code.patch b/vscode-paches/0032-cleanup-remove-non-ESM-compatible-code.patch new file mode 100644 index 00000000..e7dd30a6 --- /dev/null +++ b/vscode-paches/0032-cleanup-remove-non-ESM-compatible-code.patch @@ -0,0 +1,41 @@ +From 617d919a1dfb192e6ece326239248a51671b172d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:48:09 +0100 +Subject: [PATCH 32/58] cleanup: remove non-ESM compatible code + +--- + .../workbench/api/node/extensionHostProcess.ts | 18 ------------------ + 1 file changed, 18 deletions(-) + +diff --git a/src/vs/workbench/api/node/extensionHostProcess.ts b/src/vs/workbench/api/node/extensionHostProcess.ts +index c98941f5181..0ab601bdbfc 100644 +--- a/src/vs/workbench/api/node/extensionHostProcess.ts ++++ b/src/vs/workbench/api/node/extensionHostProcess.ts +@@ -56,24 +56,6 @@ const args = minimist(process.argv.slice(2), { + ] + }) as ParsedExtHostArgs; + +-// With Electron 2.x and node.js 8.x the "natives" module +-// can cause a native crash (see https://github.com/nodejs/node/issues/19891 and +-// https://github.com/electron/electron/issues/10905). To prevent this from +-// happening we essentially blocklist this module from getting loaded in any +-// extension by patching the node require() function. +-(function () { +- const Module = globalThis._VSCODE_NODE_MODULES.module as any; +- const originalLoad = Module._load; +- +- Module._load = function (request: string) { +- if (request === 'natives') { +- throw new Error('Either the extension or an NPM dependency is using the [unsupported "natives" node module](https://go.microsoft.com/fwlink/?linkid=871887).'); +- } +- +- return originalLoad.apply(this, arguments); +- }; +-})(); +- + // custom process.exit logic... + const nativeExit: IExitFn = process.exit.bind(process); + const nativeOn = process.on.bind(process); +-- +2.34.1 + diff --git a/vscode-paches/0033-fix-prevent-overriding-native-modules.patch b/vscode-paches/0033-fix-prevent-overriding-native-modules.patch new file mode 100644 index 00000000..0d2764d4 --- /dev/null +++ b/vscode-paches/0033-fix-prevent-overriding-native-modules.patch @@ -0,0 +1,31 @@ +From 52f92894c697406cd3d130544a66aa51039fa789 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:48:39 +0100 +Subject: [PATCH 33/58] fix: prevent overriding native modules + +--- + src/vs/workbench/api/node/proxyResolver.ts | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/vs/workbench/api/node/proxyResolver.ts b/src/vs/workbench/api/node/proxyResolver.ts +index 519924eec13..07dd94be9a2 100644 +--- a/src/vs/workbench/api/node/proxyResolver.ts ++++ b/src/vs/workbench/api/node/proxyResolver.ts +@@ -78,10 +78,10 @@ export function connectProxyResolver( + + function createPatchedModules(params: ProxyAgentParams, resolveProxy: ReturnType) { + return { +- http: Object.assign(http, createHttpPatch(params, http, resolveProxy)), +- https: Object.assign(https, createHttpPatch(params, https, resolveProxy)), +- net: Object.assign(net, createNetPatch(params, net)), +- tls: Object.assign(tls, createTlsPatch(params, tls)) ++ http: Object.assign({ ...http }, createHttpPatch(params, http, resolveProxy)), ++ https: Object.assign({ ...https }, createHttpPatch(params, https, resolveProxy)), ++ net: Object.assign({ ...net }, createNetPatch(params, net)), ++ tls: Object.assign({ ...tls }, createTlsPatch(params, tls)) + }; + } + +-- +2.34.1 + diff --git a/vscode-paches/0034-feat-expose-api-factory.patch b/vscode-paches/0034-feat-expose-api-factory.patch new file mode 100644 index 00000000..7a9bb92f --- /dev/null +++ b/vscode-paches/0034-feat-expose-api-factory.patch @@ -0,0 +1,44 @@ +From 1560c6326b050938a29a185ca522b34f479f4842 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:49:14 +0100 +Subject: [PATCH 34/58] feat: expose api factory + +--- + src/vs/workbench/api/worker/extHostExtensionService.ts | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts +index 5ce2ec7413b..5555f431ba0 100644 +--- a/src/vs/workbench/api/worker/extHostExtensionService.ts ++++ b/src/vs/workbench/api/worker/extHostExtensionService.ts +@@ -3,7 +3,7 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; ++import { IExtensionApiFactory, createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl'; + import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHostExtensionActivator'; + import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService'; + import { URI } from 'vs/base/common/uri'; +@@ -38,6 +38,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { + readonly extensionRuntime = ExtensionRuntime.Webworker; + + private _fakeModules?: WorkerRequireInterceptor; ++ protected _apiFactory?: IExtensionApiFactory; + + protected async _beforeAlmostReadyToRunExtensions(): Promise { + if (isWebWorker) { +@@ -46,8 +47,8 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { + } + + // initialize API and register actors +- const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); +- this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, { mine: this._myRegistry, all: this._globalRegistry }); ++ this._apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors); ++ this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, this._apiFactory, { mine: this._myRegistry, all: this._globalRegistry }); + await this._fakeModules.install(); + performance.mark('code/extHost/didInitAPI'); + +-- +2.34.1 + diff --git a/vscode-paches/0035-refactor-split-some-modules-to-be-able-to-import-the.patch b/vscode-paches/0035-refactor-split-some-modules-to-be-able-to-import-the.patch new file mode 100644 index 00000000..b96945cc --- /dev/null +++ b/vscode-paches/0035-refactor-split-some-modules-to-be-able-to-import-the.patch @@ -0,0 +1,1904 @@ +From 8486bec542582e44aaabfd0b637791c2d807a06a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:49:55 +0100 +Subject: [PATCH 35/58] refactor: split some modules to be able to import them + partially + +--- + .../editor/editor.autosave.contribution.ts | 9 + + .../parts/editor/editor.contribution.ts | 3 +- + .../files/browser/fileCommands.save.ts | 198 ++++++ + .../contrib/files/browser/fileCommands.ts | 245 +------ + .../files.configuration.contribution.ts | 307 +++++++++ + .../files/browser/files.contribution.ts | 633 +----------------- + .../browser/files.editorPane.contribution.ts | 94 +++ + .../browser/files.explorer.contribution.ts | 270 ++++++++ + .../files.fileEditorFactory.contribution.ts | 23 + + 9 files changed, 940 insertions(+), 842 deletions(-) + create mode 100644 src/vs/workbench/browser/parts/editor/editor.autosave.contribution.ts + create mode 100644 src/vs/workbench/contrib/files/browser/fileCommands.save.ts + create mode 100644 src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts + create mode 100644 src/vs/workbench/contrib/files/browser/files.editorPane.contribution.ts + create mode 100644 src/vs/workbench/contrib/files/browser/files.explorer.contribution.ts + create mode 100644 src/vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution.ts + +diff --git a/src/vs/workbench/browser/parts/editor/editor.autosave.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.autosave.contribution.ts +new file mode 100644 +index 00000000000..c7416d68719 +--- /dev/null ++++ b/src/vs/workbench/browser/parts/editor/editor.autosave.contribution.ts +@@ -0,0 +1,9 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave'; ++import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; ++ ++registerWorkbenchContribution2(EditorAutoSave.ID, EditorAutoSave, WorkbenchPhase.BlockRestore); +diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts +index ca21ad13864..cd246dcb75b 100644 +--- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts ++++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts +@@ -60,7 +60,6 @@ import { isMacintosh } from 'vs/base/common/platform'; + import { EditorContributionInstantiation, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; + import { FloatingEditorClickMenu } from 'vs/workbench/browser/codeeditor'; + import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; +-import { EditorAutoSave } from 'vs/workbench/browser/parts/editor/editorAutoSave'; + import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess'; + import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess, AllEditorsByAppearanceQuickAccess, AllEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess'; + import { FileAccess } from 'vs/base/common/network'; +@@ -71,6 +70,7 @@ import { DynamicEditorConfigurations } from 'vs/workbench/browser/parts/editor/e + import { EditorActionsDefaultAction, EditorActionsTitleBarAction, HideEditorActionsAction, HideEditorTabsAction, ShowMultipleEditorTabsAction, ShowSingleEditorTabAction, ZenHideEditorTabsAction, ZenShowMultipleEditorTabsAction, ZenShowSingleEditorTabAction } from 'vs/workbench/browser/actions/layoutActions'; + import { ICommandAction } from 'vs/platform/action/common/action'; + import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; ++import './editor.autosave.contribution'; + + //#region Editor Registrations + +@@ -127,7 +127,6 @@ Registry.as(EditorExtensions.EditorFactory).registerEdit + + //#region Workbench Contributions + +-registerWorkbenchContribution2(EditorAutoSave.ID, EditorAutoSave, WorkbenchPhase.BlockRestore); + registerWorkbenchContribution2(EditorStatusContribution.ID, EditorStatusContribution, WorkbenchPhase.BlockRestore); + registerWorkbenchContribution2(UntitledTextEditorWorkingCopyEditorHandler.ID, UntitledTextEditorWorkingCopyEditorHandler, WorkbenchPhase.BlockRestore); + registerWorkbenchContribution2(DynamicEditorConfigurations.ID, DynamicEditorConfigurations, WorkbenchPhase.BlockRestore); +diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.save.ts b/src/vs/workbench/contrib/files/browser/fileCommands.save.ts +new file mode 100644 +index 00000000000..e7540d3d049 +--- /dev/null ++++ b/src/vs/workbench/contrib/files/browser/fileCommands.save.ts +@@ -0,0 +1,198 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { toAction } from 'vs/base/common/actions'; ++import { coalesce } from 'vs/base/common/arrays'; ++import { toErrorMessage } from 'vs/base/common/errorMessage'; ++import { isCancellationError } from 'vs/base/common/errors'; ++import { hash } from 'vs/base/common/hash'; ++import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; ++import { isEqual } from 'vs/base/common/resources'; ++import { URI } from 'vs/base/common/uri'; ++import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; ++import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; ++import * as nls from 'vs/nls'; ++import { CommandsRegistry } from 'vs/platform/commands/common/commands'; ++import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; ++import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; ++import { IListService } from 'vs/platform/list/browser/listService'; ++import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; ++import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; ++import { EditorInputCapabilities, EditorResourceAccessor, EditorsOrder, IEditorCommandsContext, IEditorIdentifier, SaveReason, SideBySideEditor } from 'vs/workbench/common/editor'; ++import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; ++import { getOpenEditorsViewMultiSelection } from 'vs/workbench/contrib/files/browser/files'; ++import { GroupsOrder, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; ++import { IEditorService, ISaveEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; ++import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; ++import { SAVE_ALL_COMMAND_ID, SAVE_ALL_IN_GROUP_COMMAND_ID, SAVE_FILES_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID } from './fileConstants'; ++ ++async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsOptions): Promise { ++ const listService = accessor.get(IListService); ++ const editorGroupService = accessor.get(IEditorGroupsService); ++ const codeEditorService = accessor.get(ICodeEditorService); ++ const textFileService = accessor.get(ITextFileService); ++ ++ // Retrieve selected or active editor ++ let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService); ++ if (!editors) { ++ const activeGroup = editorGroupService.activeGroup; ++ if (activeGroup.activeEditor) { ++ editors = []; ++ ++ // Special treatment for side by side editors: if the active editor ++ // has 2 sides, we consider both, to support saving both sides. ++ // We only allow this when saving, not for "Save As" and not if any ++ // editor is untitled which would bring up a "Save As" dialog too. ++ // In addition, we require the secondary side to be modified to not ++ // trigger a touch operation unexpectedly. ++ // ++ // See also https://github.com/microsoft/vscode/issues/4180 ++ // See also https://github.com/microsoft/vscode/issues/106330 ++ // See also https://github.com/microsoft/vscode/issues/190210 ++ if ( ++ activeGroup.activeEditor instanceof SideBySideEditorInput && ++ !options?.saveAs && !(activeGroup.activeEditor.primary.hasCapability(EditorInputCapabilities.Untitled) || activeGroup.activeEditor.secondary.hasCapability(EditorInputCapabilities.Untitled)) && ++ activeGroup.activeEditor.secondary.isModified() ++ ) { ++ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.primary }); ++ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.secondary }); ++ } else { ++ editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor }); ++ } ++ } ++ } ++ ++ if (!editors || editors.length === 0) { ++ return; // nothing to save ++ } ++ ++ // Save editors ++ await doSaveEditors(accessor, editors, options); ++ ++ // Special treatment for embedded editors: if we detect that focus is ++ // inside an embedded code editor, we save that model as well if we ++ // find it in our text file models. Currently, only textual editors ++ // support embedded editors. ++ const focusedCodeEditor = codeEditorService.getFocusedCodeEditor(); ++ if (focusedCodeEditor instanceof EmbeddedCodeEditorWidget && !focusedCodeEditor.isSimpleWidget) { ++ const resource = focusedCodeEditor.getModel()?.uri; ++ ++ // Check that the resource of the model was not saved already ++ if (resource && !editors.some(({ editor }) => isEqual(EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }), resource))) { ++ const model = textFileService.files.get(resource); ++ if (!model?.isReadonly()) { ++ await textFileService.save(resource, options); ++ } ++ } ++ } ++} ++ ++function saveDirtyEditorsOfGroups(accessor: ServicesAccessor, groups: readonly IEditorGroup[], options?: ISaveEditorsOptions): Promise { ++ const dirtyEditors: IEditorIdentifier[] = []; ++ for (const group of groups) { ++ for (const editor of group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { ++ if (editor.isDirty()) { ++ dirtyEditors.push({ groupId: group.id, editor }); ++ } ++ } ++ } ++ ++ return doSaveEditors(accessor, dirtyEditors, options); ++} ++ ++async function doSaveEditors(accessor: ServicesAccessor, editors: IEditorIdentifier[], options?: ISaveEditorsOptions): Promise { ++ const editorService = accessor.get(IEditorService); ++ const notificationService = accessor.get(INotificationService); ++ const instantiationService = accessor.get(IInstantiationService); ++ ++ try { ++ await editorService.save(editors, options); ++ } catch (error) { ++ if (!isCancellationError(error)) { ++ notificationService.notify({ ++ id: editors.map(({ editor }) => hash(editor.resource?.toString())).join(), // ensure unique notification ID per set of editor ++ severity: Severity.Error, ++ message: nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)), ++ actions: { ++ primary: [ ++ toAction({ id: 'workbench.action.files.saveEditors', label: nls.localize('retry', "Retry"), run: () => instantiationService.invokeFunction(accessor => doSaveEditors(accessor, editors, options)) }), ++ toAction({ id: 'workbench.action.files.revertEditors', label: nls.localize('discard', "Discard"), run: () => editorService.revert(editors) }) ++ ] ++ } ++ }); ++ } ++ } ++} ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ when: undefined, ++ weight: KeybindingWeight.WorkbenchContrib, ++ primary: KeyMod.CtrlCmd | KeyCode.KeyS, ++ id: SAVE_FILE_COMMAND_ID, ++ handler: accessor => { ++ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */ }); ++ } ++}); ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ when: undefined, ++ weight: KeybindingWeight.WorkbenchContrib, ++ primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS), ++ win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS) }, ++ id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, ++ handler: accessor => { ++ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */, skipSaveParticipants: true }); ++ } ++}); ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ id: SAVE_FILE_AS_COMMAND_ID, ++ weight: KeybindingWeight.WorkbenchContrib, ++ when: undefined, ++ primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS, ++ handler: accessor => { ++ return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, saveAs: true }); ++ } ++}); ++ ++KeybindingsRegistry.registerCommandAndKeybindingRule({ ++ when: undefined, ++ weight: KeybindingWeight.WorkbenchContrib, ++ primary: undefined, ++ mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyS }, ++ win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS) }, ++ id: SAVE_ALL_COMMAND_ID, ++ handler: accessor => { ++ return saveDirtyEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); ++ } ++}); ++ ++CommandsRegistry.registerCommand({ ++ id: SAVE_ALL_IN_GROUP_COMMAND_ID, ++ handler: (accessor, _: URI | object, editorContext: IEditorCommandsContext) => { ++ const editorGroupService = accessor.get(IEditorGroupsService); ++ ++ const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService), accessor.get(IEditorGroupsService)); ++ ++ let groups: readonly IEditorGroup[] | undefined = undefined; ++ if (!contexts.length) { ++ groups = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); ++ } else { ++ groups = coalesce(contexts.map(context => editorGroupService.getGroup(context.groupId))); ++ } ++ ++ return saveDirtyEditorsOfGroups(accessor, groups, { reason: SaveReason.EXPLICIT }); ++ } ++}); ++ ++CommandsRegistry.registerCommand({ ++ id: SAVE_FILES_COMMAND_ID, ++ handler: async accessor => { ++ const editorService = accessor.get(IEditorService); ++ ++ const res = await editorService.saveAll({ includeUntitled: false, reason: SaveReason.EXPLICIT }); ++ return res.success; ++ } ++}); +diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts +index 6fa04545a0e..7fe3e6ecee1 100644 +--- a/src/vs/workbench/contrib/files/browser/fileCommands.ts ++++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts +@@ -3,56 +3,48 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import * as nls from 'vs/nls'; ++import { toErrorMessage } from 'vs/base/common/errorMessage'; ++import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; ++import { IDisposable, dispose } from 'vs/base/common/lifecycle'; ++import { Schemas } from 'vs/base/common/network'; ++import { isWeb, isWindows } from 'vs/base/common/platform'; ++import { basename, joinPath } from 'vs/base/common/resources'; + import { URI } from 'vs/base/common/uri'; +-import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, EditorsOrder, EditorInputCapabilities } from 'vs/workbench/common/editor'; +-import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; +-import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/window/common/window'; +-import { IHostService } from 'vs/workbench/services/host/browser/host'; +-import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +-import { IWorkspaceContextService, UNTITLED_WORKSPACE_NAME } from 'vs/platform/workspace/common/workspace'; +-import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, ExplorerCompressedFocusContext, ExplorerCompressedFirstFocusContext, ExplorerCompressedLastFocusContext, FilesExplorerFocusCondition, ExplorerFolderContext, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; +-import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; ++import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; ++import { ITextModelService } from 'vs/editor/common/services/resolverService'; ++import * as nls from 'vs/nls'; + import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +-import { toErrorMessage } from 'vs/base/common/errorMessage'; +-import { IListService } from 'vs/platform/list/browser/listService'; + import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands'; +-import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; ++import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; ++import { EditorOpenSource, EditorResolution } from 'vs/platform/editor/common/editor'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; + import { IFileService } from 'vs/platform/files/common/files'; +-import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +-import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; +-import { isWeb, isWindows } from 'vs/base/common/platform'; +-import { ITextModelService } from 'vs/editor/common/services/resolverService'; +-import { getResourceForCommand, getMultiSelectedResources, getOpenEditorsViewMultiSelection, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +-import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; +-import { getMultiSelectedEditorContexts } from 'vs/workbench/browser/parts/editor/editorCommands'; +-import { Schemas } from 'vs/base/common/network'; +-import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +-import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +-import { IEditorService, SIDE_GROUP, ISaveEditorsOptions } from 'vs/workbench/services/editor/common/editorService'; +-import { IEditorGroupsService, GroupsOrder, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; ++import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; ++import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; + import { ILabelService } from 'vs/platform/label/common/label'; +-import { basename, joinPath, isEqual } from 'vs/base/common/resources'; +-import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +-import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +-import { coalesce } from 'vs/base/common/arrays'; +-import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +-import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; +-import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; ++import { IListService } from 'vs/platform/list/browser/listService'; ++import { INotificationService } from 'vs/platform/notification/common/notification'; + import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; +-import { isCancellationError } from 'vs/base/common/errors'; +-import { toAction } from 'vs/base/common/actions'; +-import { EditorOpenSource, EditorResolution } from 'vs/platform/editor/common/editor'; +-import { hash } from 'vs/base/common/hash'; +-import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +-import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; +-import { ViewContainerLocation } from 'vs/workbench/common/views'; +-import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; +-import { OPEN_TO_SIDE_COMMAND_ID, COMPARE_WITH_SAVED_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, COMPARE_SELECTED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, COPY_PATH_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_WITH_EXPLORER_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_ALL_COMMAND_ID, SAVE_ALL_IN_GROUP_COMMAND_ID, SAVE_FILES_COMMAND_ID, REVERT_FILE_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, PREVIOUS_COMPRESSED_FOLDER, NEXT_COMPRESSED_FOLDER, FIRST_COMPRESSED_FOLDER, LAST_COMPRESSED_FOLDER, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL, NEW_FILE_COMMAND_ID } from './fileConstants'; +-import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; ++import { IOpenEmptyWindowOptions, IOpenWindowOptions, IWindowOpenable, isWorkspaceToOpen } from 'vs/platform/window/common/window'; ++import { IWorkspaceContextService, UNTITLED_WORKSPACE_NAME } from 'vs/platform/workspace/common/workspace'; + import { RemoveRootFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; +-import { OpenEditorsView } from 'vs/workbench/contrib/files/browser/views/openEditorsView'; ++import { EditorInputCapabilities, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; ++import { ViewContainerLocation } from 'vs/workbench/common/views'; ++import { ExplorerViewPaneContainer } from 'vs/workbench/contrib/files/browser/explorerViewlet'; ++import { IExplorerService, getMultiSelectedResources, getOpenEditorsViewMultiSelection, getResourceForCommand } from 'vs/workbench/contrib/files/browser/files'; + import { ExplorerView } from 'vs/workbench/contrib/files/browser/views/explorerView'; ++import { OpenEditorsView } from 'vs/workbench/contrib/files/browser/views/openEditorsView'; ++import { ExplorerCompressedFirstFocusContext, ExplorerCompressedFocusContext, ExplorerCompressedLastFocusContext, ExplorerFocusCondition, ExplorerFolderContext, FilesExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, VIEW_ID } from 'vs/workbench/contrib/files/common/files'; ++import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; ++import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; ++import { IHostService } from 'vs/workbench/services/host/browser/host'; ++import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; ++import { IViewsService } from 'vs/workbench/services/views/common/viewsService'; ++import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; ++import { COMPARE_RESOURCE_COMMAND_ID, COMPARE_SELECTED_COMMAND_ID, COMPARE_WITH_SAVED_COMMAND_ID, COPY_PATH_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, FIRST_COMPRESSED_FOLDER, LAST_COMPRESSED_FOLDER, NEW_FILE_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL, NEXT_COMPRESSED_FOLDER, OPEN_TO_SIDE_COMMAND_ID, OPEN_WITH_EXPLORER_COMMAND_ID, PREVIOUS_COMPRESSED_FOLDER, REMOVE_ROOT_FOLDER_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, REVERT_FILE_COMMAND_ID, ResourceSelectedForCompareContext, SELECT_FOR_COMPARE_COMMAND_ID } from './fileConstants'; ++import './fileCommands.save'; + + export const openWindowCommand = (accessor: ServicesAccessor, toOpen: IWindowOpenable[], options?: IOpenWindowOptions) => { + if (Array.isArray(toOpen)) { +@@ -366,175 +358,6 @@ CommandsRegistry.registerCommand({ + + // Save / Save As / Save All / Revert + +-async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsOptions): Promise { +- const listService = accessor.get(IListService); +- const editorGroupService = accessor.get(IEditorGroupsService); +- const codeEditorService = accessor.get(ICodeEditorService); +- const textFileService = accessor.get(ITextFileService); +- +- // Retrieve selected or active editor +- let editors = getOpenEditorsViewMultiSelection(listService, editorGroupService); +- if (!editors) { +- const activeGroup = editorGroupService.activeGroup; +- if (activeGroup.activeEditor) { +- editors = []; +- +- // Special treatment for side by side editors: if the active editor +- // has 2 sides, we consider both, to support saving both sides. +- // We only allow this when saving, not for "Save As" and not if any +- // editor is untitled which would bring up a "Save As" dialog too. +- // In addition, we require the secondary side to be modified to not +- // trigger a touch operation unexpectedly. +- // +- // See also https://github.com/microsoft/vscode/issues/4180 +- // See also https://github.com/microsoft/vscode/issues/106330 +- // See also https://github.com/microsoft/vscode/issues/190210 +- if ( +- activeGroup.activeEditor instanceof SideBySideEditorInput && +- !options?.saveAs && !(activeGroup.activeEditor.primary.hasCapability(EditorInputCapabilities.Untitled) || activeGroup.activeEditor.secondary.hasCapability(EditorInputCapabilities.Untitled)) && +- activeGroup.activeEditor.secondary.isModified() +- ) { +- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.primary }); +- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.secondary }); +- } else { +- editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor }); +- } +- } +- } +- +- if (!editors || editors.length === 0) { +- return; // nothing to save +- } +- +- // Save editors +- await doSaveEditors(accessor, editors, options); +- +- // Special treatment for embedded editors: if we detect that focus is +- // inside an embedded code editor, we save that model as well if we +- // find it in our text file models. Currently, only textual editors +- // support embedded editors. +- const focusedCodeEditor = codeEditorService.getFocusedCodeEditor(); +- if (focusedCodeEditor instanceof EmbeddedCodeEditorWidget && !focusedCodeEditor.isSimpleWidget) { +- const resource = focusedCodeEditor.getModel()?.uri; +- +- // Check that the resource of the model was not saved already +- if (resource && !editors.some(({ editor }) => isEqual(EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }), resource))) { +- const model = textFileService.files.get(resource); +- if (!model?.isReadonly()) { +- await textFileService.save(resource, options); +- } +- } +- } +-} +- +-function saveDirtyEditorsOfGroups(accessor: ServicesAccessor, groups: readonly IEditorGroup[], options?: ISaveEditorsOptions): Promise { +- const dirtyEditors: IEditorIdentifier[] = []; +- for (const group of groups) { +- for (const editor of group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { +- if (editor.isDirty()) { +- dirtyEditors.push({ groupId: group.id, editor }); +- } +- } +- } +- +- return doSaveEditors(accessor, dirtyEditors, options); +-} +- +-async function doSaveEditors(accessor: ServicesAccessor, editors: IEditorIdentifier[], options?: ISaveEditorsOptions): Promise { +- const editorService = accessor.get(IEditorService); +- const notificationService = accessor.get(INotificationService); +- const instantiationService = accessor.get(IInstantiationService); +- +- try { +- await editorService.save(editors, options); +- } catch (error) { +- if (!isCancellationError(error)) { +- notificationService.notify({ +- id: editors.map(({ editor }) => hash(editor.resource?.toString())).join(), // ensure unique notification ID per set of editor +- severity: Severity.Error, +- message: nls.localize({ key: 'genericSaveError', comment: ['{0} is the resource that failed to save and {1} the error message'] }, "Failed to save '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false)), +- actions: { +- primary: [ +- toAction({ id: 'workbench.action.files.saveEditors', label: nls.localize('retry', "Retry"), run: () => instantiationService.invokeFunction(accessor => doSaveEditors(accessor, editors, options)) }), +- toAction({ id: 'workbench.action.files.revertEditors', label: nls.localize('discard', "Discard"), run: () => editorService.revert(editors) }) +- ] +- } +- }); +- } +- } +-} +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- when: undefined, +- weight: KeybindingWeight.WorkbenchContrib, +- primary: KeyMod.CtrlCmd | KeyCode.KeyS, +- id: SAVE_FILE_COMMAND_ID, +- handler: accessor => { +- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */ }); +- } +-}); +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- when: undefined, +- weight: KeybindingWeight.WorkbenchContrib, +- primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS), +- win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS) }, +- id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, +- handler: accessor => { +- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true /* force save even when non-dirty */, skipSaveParticipants: true }); +- } +-}); +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- id: SAVE_FILE_AS_COMMAND_ID, +- weight: KeybindingWeight.WorkbenchContrib, +- when: undefined, +- primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyS, +- handler: accessor => { +- return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, saveAs: true }); +- } +-}); +- +-KeybindingsRegistry.registerCommandAndKeybindingRule({ +- when: undefined, +- weight: KeybindingWeight.WorkbenchContrib, +- primary: undefined, +- mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KeyS }, +- win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyS) }, +- id: SAVE_ALL_COMMAND_ID, +- handler: accessor => { +- return saveDirtyEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); +- } +-}); +- +-CommandsRegistry.registerCommand({ +- id: SAVE_ALL_IN_GROUP_COMMAND_ID, +- handler: (accessor, _: URI | object, editorContext: IEditorCommandsContext) => { +- const editorGroupService = accessor.get(IEditorGroupsService); +- +- const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService), accessor.get(IEditorGroupsService)); +- +- let groups: readonly IEditorGroup[] | undefined = undefined; +- if (!contexts.length) { +- groups = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); +- } else { +- groups = coalesce(contexts.map(context => editorGroupService.getGroup(context.groupId))); +- } +- +- return saveDirtyEditorsOfGroups(accessor, groups, { reason: SaveReason.EXPLICIT }); +- } +-}); +- +-CommandsRegistry.registerCommand({ +- id: SAVE_FILES_COMMAND_ID, +- handler: async accessor => { +- const editorService = accessor.get(IEditorService); +- +- const res = await editorService.saveAll({ includeUntitled: false, reason: SaveReason.EXPLICIT }); +- return res.success; +- } +-}); +- + CommandsRegistry.registerCommand({ + id: REVERT_FILE_COMMAND_ID, + handler: async accessor => { +diff --git a/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts b/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts +new file mode 100644 +index 00000000000..39509160248 +--- /dev/null ++++ b/src/vs/workbench/contrib/files/browser/files.configuration.contribution.ts +@@ -0,0 +1,307 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { isNative, isWeb } from 'vs/base/common/platform'; ++import { editorConfigurationBaseNode } from 'vs/editor/common/config/editorConfigurationSchema'; ++import * as nls from 'vs/nls'; ++import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; ++import { AutoSaveConfiguration, FILES_ASSOCIATIONS_CONFIG, FILES_EXCLUDE_CONFIG, FILES_READONLY_EXCLUDE_CONFIG, FILES_READONLY_FROM_PERMISSIONS_CONFIG, FILES_READONLY_INCLUDE_CONFIG, HotExitConfiguration } from 'vs/platform/files/common/files'; ++import { Registry } from 'vs/platform/registry/common/platform'; ++import { SUPPORTED_ENCODINGS } from 'vs/workbench/services/textfile/common/encoding'; ++ ++// Configuration ++const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); ++ ++const hotExitConfiguration: IConfigurationPropertySchema = isNative ? ++ { ++ 'type': 'string', ++ 'scope': ConfigurationScope.APPLICATION, ++ 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], ++ 'default': HotExitConfiguration.ON_EXIT, ++ 'markdownEnumDescriptions': [ ++ nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), ++ nls.localize('hotExit.onExit', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu). All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`'), ++ nls.localize('hotExit.onExitAndWindowClose', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu), and also for any window with a folder opened regardless of whether it\'s the last window. All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`') ++ ], ++ 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) ++ } : { ++ 'type': 'string', ++ 'scope': ConfigurationScope.APPLICATION, ++ 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], ++ 'default': HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, ++ 'markdownEnumDescriptions': [ ++ nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), ++ nls.localize('hotExit.onExitAndWindowCloseBrowser', 'Hot exit will be triggered when the browser quits or the window or tab is closed.') ++ ], ++ 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) ++ }; ++ ++configurationRegistry.registerConfiguration({ ++ 'id': 'files', ++ 'order': 9, ++ 'title': nls.localize('filesConfigurationTitle', "Files"), ++ 'type': 'object', ++ 'properties': { ++ [FILES_EXCLUDE_CONFIG]: { ++ 'type': 'object', ++ 'markdownDescription': nls.localize('exclude', "Configure [glob patterns](https://aka.ms/vscode-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. Refer to the `#search.exclude#` setting to define search-specific excludes. Refer to the `#explorer.excludeGitIgnore#` setting for ignoring files based on your `.gitignore`."), ++ 'default': { ++ ...{ '**/.git': true, '**/.svn': true, '**/.hg': true, '**/CVS': true, '**/.DS_Store': true, '**/Thumbs.db': true }, ++ ...(isWeb ? { '**/*.crswap': true /* filter out swap files used for local file access */ } : undefined) ++ }, ++ 'scope': ConfigurationScope.RESOURCE, ++ 'additionalProperties': { ++ 'anyOf': [ ++ { ++ 'type': 'boolean', ++ 'enum': [true, false], ++ 'enumDescriptions': [nls.localize('trueDescription', "Enable the pattern."), nls.localize('falseDescription', "Disable the pattern.")], ++ 'description': nls.localize('files.exclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), ++ }, ++ { ++ 'type': 'object', ++ 'properties': { ++ 'when': { ++ 'type': 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) ++ 'pattern': '\\w*\\$\\(basename\\)\\w*', ++ 'default': '$(basename).ext', ++ 'markdownDescription': nls.localize({ key: 'files.exclude.when', comment: ['\\$(basename) should not be translated'] }, "Additional check on the siblings of a matching file. Use \\$(basename) as variable for the matching file name.") ++ } ++ } ++ } ++ ] ++ } ++ }, ++ [FILES_ASSOCIATIONS_CONFIG]: { ++ 'type': 'object', ++ 'markdownDescription': nls.localize('associations', "Configure [glob patterns](https://aka.ms/vscode-glob-patterns) of file associations to languages (for example `\"*.extension\": \"html\"`). Patterns will match on the absolute path of a file if they contain a path separator and will match on the name of the file otherwise. These have precedence over the default associations of the languages installed."), ++ 'additionalProperties': { ++ 'type': 'string' ++ } ++ }, ++ 'files.encoding': { ++ 'type': 'string', ++ 'enum': Object.keys(SUPPORTED_ENCODINGS), ++ 'default': 'utf8', ++ 'description': nls.localize('encoding', "The default character set encoding to use when reading and writing files. This setting can also be configured per language."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, ++ 'enumDescriptions': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong), ++ 'enumItemLabels': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong) ++ }, ++ 'files.autoGuessEncoding': { ++ 'type': 'boolean', ++ 'default': false, ++ 'markdownDescription': nls.localize('autoGuessEncoding', "When enabled, the editor will attempt to guess the character set encoding when opening files. This setting can also be configured per language. Note, this setting is not respected by text search. Only {0} is respected.", '`#files.encoding#`'), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.eol': { ++ 'type': 'string', ++ 'enum': [ ++ '\n', ++ '\r\n', ++ 'auto' ++ ], ++ 'enumDescriptions': [ ++ nls.localize('eol.LF', "LF"), ++ nls.localize('eol.CRLF', "CRLF"), ++ nls.localize('eol.auto', "Uses operating system specific end of line character.") ++ ], ++ 'default': 'auto', ++ 'description': nls.localize('eol', "The default end of line character."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.enableTrash': { ++ 'type': 'boolean', ++ 'default': true, ++ 'description': nls.localize('useTrash', "Moves files/folders to the OS trash (recycle bin on Windows) when deleting. Disabling this will delete files/folders permanently.") ++ }, ++ 'files.trimTrailingWhitespace': { ++ 'type': 'boolean', ++ 'default': false, ++ 'description': nls.localize('trimTrailingWhitespace', "When enabled, will trim trailing whitespace when saving a file."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.insertFinalNewline': { ++ 'type': 'boolean', ++ 'default': false, ++ 'description': nls.localize('insertFinalNewline', "When enabled, insert a final new line at the end of the file when saving it."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.trimFinalNewlines': { ++ 'type': 'boolean', ++ 'default': false, ++ 'description': nls.localize('trimFinalNewlines', "When enabled, will trim all new lines after the final new line at the end of the file when saving it."), ++ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE, ++ }, ++ 'files.autoSave': { ++ 'type': 'string', ++ 'enum': [AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE], ++ 'markdownEnumDescriptions': [ ++ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.off' }, "An editor with changes is never automatically saved."), ++ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.afterDelay' }, "An editor with changes is automatically saved after the configured `#files.autoSaveDelay#`."), ++ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onFocusChange' }, "An editor with changes is automatically saved when the editor loses focus."), ++ nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onWindowChange' }, "An editor with changes is automatically saved when the window loses focus.") ++ ], ++ 'default': isWeb ? AutoSaveConfiguration.AFTER_DELAY : AutoSaveConfiguration.OFF, ++ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSave' }, "Controls [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors that have unsaved changes.", AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE, AutoSaveConfiguration.AFTER_DELAY), ++ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.autoSaveDelay': { ++ 'type': 'number', ++ 'default': 1000, ++ 'minimum': 0, ++ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveDelay' }, "Controls the delay in milliseconds after which an editor with unsaved changes is saved automatically. Only applies when `#files.autoSave#` is set to `{0}`.", AutoSaveConfiguration.AFTER_DELAY), ++ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.autoSaveWorkspaceFilesOnly': { ++ 'type': 'boolean', ++ 'default': false, ++ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWorkspaceFilesOnly' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that are inside the opened workspace. Only applies when `#files.autoSave#` is enabled."), ++ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.autoSaveWhenNoErrors': { ++ 'type': 'boolean', ++ 'default': false, ++ 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWhenNoErrors' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that have no errors reported in them at the time the auto save is triggered. Only applies when `#files.autoSave#` is enabled."), ++ scope: ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.watcherExclude': { ++ 'type': 'object', ++ 'patternProperties': { ++ '.*': { 'type': 'boolean' } ++ }, ++ 'default': { '**/.git/objects/**': true, '**/.git/subtree-cache/**': true, '**/node_modules/*/**': true, '**/.hg/store/**': true }, ++ 'markdownDescription': nls.localize('watcherExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from file watching. Paths can either be relative to the watched folder or absolute. Glob patterns are matched relative from the watched folder. When you experience the file watcher process consuming a lot of CPU, make sure to exclude large folders that are of less interest (such as build output folders)."), ++ 'scope': ConfigurationScope.RESOURCE ++ }, ++ 'files.watcherInclude': { ++ 'type': 'array', ++ 'items': { ++ 'type': 'string' ++ }, ++ 'default': [], ++ 'description': nls.localize('watcherInclude', "Configure extra paths to watch for changes inside the workspace. By default, all workspace folders will be watched recursively, except for folders that are symbolic links. You can explicitly add absolute or relative paths to support watching folders that are symbolic links. Relative paths will be resolved to an absolute path using the currently opened workspace."), ++ 'scope': ConfigurationScope.RESOURCE ++ }, ++ 'files.hotExit': hotExitConfiguration, ++ 'files.defaultLanguage': { ++ 'type': 'string', ++ 'markdownDescription': nls.localize('defaultLanguage', "The default language identifier that is assigned to new files. If configured to `${activeEditorLanguage}`, will use the language identifier of the currently active text editor if any.") ++ }, ++ [FILES_READONLY_INCLUDE_CONFIG]: { ++ 'type': 'object', ++ 'patternProperties': { ++ '.*': { 'type': 'boolean' } ++ }, ++ 'default': {}, ++ 'markdownDescription': nls.localize('filesReadonlyInclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to mark as read-only. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. You can exclude matching paths via the `#files.readonlyExclude#` setting. Files from readonly file system providers will always be read-only independent of this setting."), ++ 'scope': ConfigurationScope.RESOURCE ++ }, ++ [FILES_READONLY_EXCLUDE_CONFIG]: { ++ 'type': 'object', ++ 'patternProperties': { ++ '.*': { 'type': 'boolean' } ++ }, ++ 'default': {}, ++ 'markdownDescription': nls.localize('filesReadonlyExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from being marked as read-only if they match as a result of the `#files.readonlyInclude#` setting. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. Files from readonly file system providers will always be read-only independent of this setting."), ++ 'scope': ConfigurationScope.RESOURCE ++ }, ++ [FILES_READONLY_FROM_PERMISSIONS_CONFIG]: { ++ 'type': 'boolean', ++ 'markdownDescription': nls.localize('filesReadonlyFromPermissions', "Marks files as read-only when their file permissions indicate as such. This can be overridden via `#files.readonlyInclude#` and `#files.readonlyExclude#` settings."), ++ 'default': false ++ }, ++ 'files.restoreUndoStack': { ++ 'type': 'boolean', ++ 'description': nls.localize('files.restoreUndoStack', "Restore the undo stack when a file is reopened."), ++ 'default': true ++ }, ++ 'files.saveConflictResolution': { ++ 'type': 'string', ++ 'enum': [ ++ 'askUser', ++ 'overwriteFileOnDisk' ++ ], ++ 'enumDescriptions': [ ++ nls.localize('askUser', "Will refuse to save and ask for resolving the save conflict manually."), ++ nls.localize('overwriteFileOnDisk', "Will resolve the save conflict by overwriting the file on disk with the changes in the editor.") ++ ], ++ 'description': nls.localize('files.saveConflictResolution', "A save conflict can occur when a file is saved to disk that was changed by another program in the meantime. To prevent data loss, the user is asked to compare the changes in the editor with the version on disk. This setting should only be changed if you frequently encounter save conflict errors and may result in data loss if used without caution."), ++ 'default': 'askUser', ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE ++ }, ++ 'files.dialog.defaultPath': { ++ 'type': 'string', ++ 'pattern': '^((\\/|\\\\\\\\|[a-zA-Z]:\\\\).*)?$', // slash OR UNC-root OR drive-root OR undefined ++ 'patternErrorMessage': nls.localize('defaultPathErrorMessage', "Default path for file dialogs must be an absolute path (e.g. C:\\\\myFolder or /myFolder)."), ++ 'description': nls.localize('fileDialogDefaultPath', "Default path for file dialogs, overriding user's home path. Only used in the absence of a context-specific path, such as most recently opened file or folder."), ++ 'scope': ConfigurationScope.MACHINE ++ }, ++ 'files.simpleDialog.enable': { ++ 'type': 'boolean', ++ 'description': nls.localize('files.simpleDialog.enable', "Enables the simple file dialog for opening and saving files and folders. The simple file dialog replaces the system file dialog when enabled."), ++ 'default': false ++ }, ++ 'files.participants.timeout': { ++ type: 'number', ++ default: 60000, ++ markdownDescription: nls.localize('files.participants.timeout', "Timeout in milliseconds after which file participants for create, rename, and delete are cancelled. Use `0` to disable participants."), ++ } ++ } ++}); ++ ++configurationRegistry.registerConfiguration({ ++ ...editorConfigurationBaseNode, ++ properties: { ++ 'editor.formatOnSave': { ++ 'type': 'boolean', ++ 'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be saved after delay, and the editor must not be shutting down."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, ++ }, ++ 'editor.formatOnSaveMode': { ++ 'type': 'string', ++ 'default': 'file', ++ 'enum': [ ++ 'file', ++ 'modifications', ++ 'modificationsIfAvailable' ++ ], ++ 'enumDescriptions': [ ++ nls.localize({ key: 'everything', comment: ['This is the description of an option'] }, "Format the whole file."), ++ nls.localize({ key: 'modification', comment: ['This is the description of an option'] }, "Format modifications (requires source control)."), ++ nls.localize({ key: 'modificationIfAvailable', comment: ['This is the description of an option'] }, "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted."), ++ ], ++ 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is enabled."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, ++ }, ++ } ++}); ++ ++configurationRegistry.registerConfiguration({ ++ ...editorConfigurationBaseNode, ++ properties: { ++ 'editor.formatOnSave': { ++ 'type': 'boolean', ++ 'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be saved after delay, and the editor must not be shutting down."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, ++ }, ++ 'editor.formatOnSaveMode': { ++ 'type': 'string', ++ 'default': 'file', ++ 'enum': [ ++ 'file', ++ 'modifications', ++ 'modificationsIfAvailable' ++ ], ++ 'enumDescriptions': [ ++ nls.localize({ key: 'everything', comment: ['This is the description of an option'] }, "Format the whole file."), ++ nls.localize({ key: 'modification', comment: ['This is the description of an option'] }, "Format modifications (requires source control)."), ++ nls.localize({ key: 'modificationIfAvailable', comment: ['This is the description of an option'] }, "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted."), ++ ], ++ 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is enabled."), ++ 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, ++ }, ++ } ++}); +diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts +index 80162ffd007..98d8dec26be 100644 +--- a/src/vs/workbench/contrib/files/browser/files.contribution.ts ++++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts +@@ -3,632 +3,7 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import * as nls from 'vs/nls'; +-import { sep } from 'vs/base/common/path'; +-import { Registry } from 'vs/platform/registry/common/platform'; +-import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; +-import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; +-import { IFileEditorInput, IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +-import { AutoSaveConfiguration, HotExitConfiguration, FILES_EXCLUDE_CONFIG, FILES_ASSOCIATIONS_CONFIG, FILES_READONLY_INCLUDE_CONFIG, FILES_READONLY_EXCLUDE_CONFIG, FILES_READONLY_FROM_PERMISSIONS_CONFIG } from 'vs/platform/files/common/files'; +-import { SortOrder, LexicographicOptions, FILE_EDITOR_INPUT_ID, BINARY_TEXT_FILE_MODE, UndoConfirmLevel, IFilesConfiguration } from 'vs/workbench/contrib/files/common/files'; +-import { TextFileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/textFileEditorTracker'; +-import { TextFileSaveErrorHandler } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; +-import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; +-import { BinaryFileEditor } from 'vs/workbench/contrib/files/browser/editors/binaryFileEditor'; +-import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +-import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +-import { isNative, isWeb, isWindows } from 'vs/base/common/platform'; +-import { ExplorerViewletViewsContribution } from 'vs/workbench/contrib/files/browser/explorerViewlet'; +-import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/editor'; +-import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +-import { ILabelService } from 'vs/platform/label/common/label'; +-import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; +-import { ExplorerService, UNDO_REDO_SOURCE } from 'vs/workbench/contrib/files/browser/explorerService'; +-import { SUPPORTED_ENCODINGS } from 'vs/workbench/services/textfile/common/encoding'; +-import { Schemas } from 'vs/base/common/network'; +-import { WorkspaceWatcher } from 'vs/workbench/contrib/files/browser/workspaceWatcher'; +-import { editorConfigurationBaseNode } from 'vs/editor/common/config/editorConfigurationSchema'; +-import { DirtyFilesIndicator } from 'vs/workbench/contrib/files/common/dirtyFilesIndicator'; +-import { UndoCommand, RedoCommand } from 'vs/editor/browser/editorExtensions'; +-import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; +-import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +-import { FileEditorInputSerializer, FileEditorWorkingCopyEditorHandler } from 'vs/workbench/contrib/files/browser/editors/fileEditorHandler'; +-import { ModesRegistry } from 'vs/editor/common/languages/modesRegistry'; +-import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +-import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; +- +-class FileUriLabelContribution implements IWorkbenchContribution { +- +- static readonly ID = 'workbench.contrib.fileUriLabel'; +- +- constructor(@ILabelService labelService: ILabelService) { +- labelService.registerFormatter({ +- scheme: Schemas.file, +- formatting: { +- label: '${authority}${path}', +- separator: sep, +- tildify: !isWindows, +- normalizeDriveLetter: isWindows, +- authorityPrefix: sep + sep, +- workspaceSuffix: '' +- } +- }); +- } +-} +- +-registerSingleton(IExplorerService, ExplorerService, InstantiationType.Delayed); +- +-// Register file editors +- +-Registry.as(EditorExtensions.EditorPane).registerEditorPane( +- EditorPaneDescriptor.create( +- TextFileEditor, +- TextFileEditor.ID, +- nls.localize('textFileEditor', "Text File Editor") +- ), +- [ +- new SyncDescriptor(FileEditorInput) +- ] +-); +- +-Registry.as(EditorExtensions.EditorPane).registerEditorPane( +- EditorPaneDescriptor.create( +- BinaryFileEditor, +- BinaryFileEditor.ID, +- nls.localize('binaryFileEditor', "Binary File Editor") +- ), +- [ +- new SyncDescriptor(FileEditorInput) +- ] +-); +- +-// Register default file input factory +-Registry.as(EditorExtensions.EditorFactory).registerFileEditorFactory({ +- +- typeId: FILE_EDITOR_INPUT_ID, +- +- createFileEditor: (resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents, instantiationService): IFileEditorInput => { +- return instantiationService.createInstance(FileEditorInput, resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents); +- }, +- +- isFileEditor: (obj): obj is IFileEditorInput => { +- return obj instanceof FileEditorInput; +- } +-}); +- +-// Register Editor Input Serializer & Handler +-Registry.as(EditorExtensions.EditorFactory).registerEditorSerializer(FILE_EDITOR_INPUT_ID, FileEditorInputSerializer); +-registerWorkbenchContribution2(FileEditorWorkingCopyEditorHandler.ID, FileEditorWorkingCopyEditorHandler, WorkbenchPhase.BlockRestore); +- +-// Register Explorer views +-registerWorkbenchContribution2(ExplorerViewletViewsContribution.ID, ExplorerViewletViewsContribution, WorkbenchPhase.BlockStartup); +- +-// Register Text File Editor Tracker +-registerWorkbenchContribution2(TextFileEditorTracker.ID, TextFileEditorTracker, WorkbenchPhase.BlockStartup); +- +-// Register Text File Save Error Handler +-registerWorkbenchContribution2(TextFileSaveErrorHandler.ID, TextFileSaveErrorHandler, WorkbenchPhase.BlockStartup); +- +-// Register uri display for file uris +-registerWorkbenchContribution2(FileUriLabelContribution.ID, FileUriLabelContribution, WorkbenchPhase.BlockStartup); +- +-// Register Workspace Watcher +-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored); +- +-// Register Dirty Files Indicator +-registerWorkbenchContribution2(DirtyFilesIndicator.ID, DirtyFilesIndicator, WorkbenchPhase.BlockStartup); +- +-// Configuration +-const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); +- +-const hotExitConfiguration: IConfigurationPropertySchema = isNative ? +- { +- 'type': 'string', +- 'scope': ConfigurationScope.APPLICATION, +- 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], +- 'default': HotExitConfiguration.ON_EXIT, +- 'markdownEnumDescriptions': [ +- nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), +- nls.localize('hotExit.onExit', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu). All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`'), +- nls.localize('hotExit.onExitAndWindowClose', 'Hot exit will be triggered when the last window is closed on Windows/Linux or when the `workbench.action.quit` command is triggered (command palette, keybinding, menu), and also for any window with a folder opened regardless of whether it\'s the last window. All windows without folders opened will be restored upon next launch. A list of previously opened windows with unsaved files can be accessed via `File > Open Recent > More...`') +- ], +- 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) +- } : { +- 'type': 'string', +- 'scope': ConfigurationScope.APPLICATION, +- 'enum': [HotExitConfiguration.OFF, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE], +- 'default': HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE, +- 'markdownEnumDescriptions': [ +- nls.localize('hotExit.off', 'Disable hot exit. A prompt will show when attempting to close a window with editors that have unsaved changes.'), +- nls.localize('hotExit.onExitAndWindowCloseBrowser', 'Hot exit will be triggered when the browser quits or the window or tab is closed.') +- ], +- 'markdownDescription': nls.localize('hotExit', "[Hot Exit](https://aka.ms/vscode-hot-exit) controls whether unsaved files are remembered between sessions, allowing the save prompt when exiting the editor to be skipped.", HotExitConfiguration.ON_EXIT, HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) +- }; +- +-configurationRegistry.registerConfiguration({ +- 'id': 'files', +- 'order': 9, +- 'title': nls.localize('filesConfigurationTitle', "Files"), +- 'type': 'object', +- 'properties': { +- [FILES_EXCLUDE_CONFIG]: { +- 'type': 'object', +- 'markdownDescription': nls.localize('exclude', "Configure [glob patterns](https://aka.ms/vscode-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. Refer to the `#search.exclude#` setting to define search-specific excludes. Refer to the `#explorer.excludeGitIgnore#` setting for ignoring files based on your `.gitignore`."), +- 'default': { +- ...{ '**/.git': true, '**/.svn': true, '**/.hg': true, '**/CVS': true, '**/.DS_Store': true, '**/Thumbs.db': true }, +- ...(isWeb ? { '**/*.crswap': true /* filter out swap files used for local file access */ } : undefined) +- }, +- 'scope': ConfigurationScope.RESOURCE, +- 'additionalProperties': { +- 'anyOf': [ +- { +- 'type': 'boolean', +- 'enum': [true, false], +- 'enumDescriptions': [nls.localize('trueDescription', "Enable the pattern."), nls.localize('falseDescription', "Disable the pattern.")], +- 'description': nls.localize('files.exclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), +- }, +- { +- 'type': 'object', +- 'properties': { +- 'when': { +- 'type': 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) +- 'pattern': '\\w*\\$\\(basename\\)\\w*', +- 'default': '$(basename).ext', +- 'markdownDescription': nls.localize({ key: 'files.exclude.when', comment: ['\\$(basename) should not be translated'] }, "Additional check on the siblings of a matching file. Use \\$(basename) as variable for the matching file name.") +- } +- } +- } +- ] +- } +- }, +- [FILES_ASSOCIATIONS_CONFIG]: { +- 'type': 'object', +- 'markdownDescription': nls.localize('associations', "Configure [glob patterns](https://aka.ms/vscode-glob-patterns) of file associations to languages (for example `\"*.extension\": \"html\"`). Patterns will match on the absolute path of a file if they contain a path separator and will match on the name of the file otherwise. These have precedence over the default associations of the languages installed."), +- 'additionalProperties': { +- 'type': 'string' +- } +- }, +- 'files.encoding': { +- 'type': 'string', +- 'enum': Object.keys(SUPPORTED_ENCODINGS), +- 'default': 'utf8', +- 'description': nls.localize('encoding', "The default character set encoding to use when reading and writing files. This setting can also be configured per language."), +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, +- 'enumDescriptions': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong), +- 'enumItemLabels': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong) +- }, +- 'files.autoGuessEncoding': { +- 'type': 'boolean', +- 'default': false, +- 'markdownDescription': nls.localize('autoGuessEncoding', "When enabled, the editor will attempt to guess the character set encoding when opening files. This setting can also be configured per language. Note, this setting is not respected by text search. Only {0} is respected.", '`#files.encoding#`'), +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.eol': { +- 'type': 'string', +- 'enum': [ +- '\n', +- '\r\n', +- 'auto' +- ], +- 'enumDescriptions': [ +- nls.localize('eol.LF', "LF"), +- nls.localize('eol.CRLF', "CRLF"), +- nls.localize('eol.auto', "Uses operating system specific end of line character.") +- ], +- 'default': 'auto', +- 'description': nls.localize('eol', "The default end of line character."), +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.enableTrash': { +- 'type': 'boolean', +- 'default': true, +- 'description': nls.localize('useTrash', "Moves files/folders to the OS trash (recycle bin on Windows) when deleting. Disabling this will delete files/folders permanently.") +- }, +- 'files.trimTrailingWhitespace': { +- 'type': 'boolean', +- 'default': false, +- 'description': nls.localize('trimTrailingWhitespace', "When enabled, will trim trailing whitespace when saving a file."), +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.insertFinalNewline': { +- 'type': 'boolean', +- 'default': false, +- 'description': nls.localize('insertFinalNewline', "When enabled, insert a final new line at the end of the file when saving it."), +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.trimFinalNewlines': { +- 'type': 'boolean', +- 'default': false, +- 'description': nls.localize('trimFinalNewlines', "When enabled, will trim all new lines after the final new line at the end of the file when saving it."), +- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE, +- }, +- 'files.autoSave': { +- 'type': 'string', +- 'enum': [AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE], +- 'markdownEnumDescriptions': [ +- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.off' }, "An editor with changes is never automatically saved."), +- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.afterDelay' }, "An editor with changes is automatically saved after the configured `#files.autoSaveDelay#`."), +- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onFocusChange' }, "An editor with changes is automatically saved when the editor loses focus."), +- nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'files.autoSave.onWindowChange' }, "An editor with changes is automatically saved when the window loses focus.") +- ], +- 'default': isWeb ? AutoSaveConfiguration.AFTER_DELAY : AutoSaveConfiguration.OFF, +- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSave' }, "Controls [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors that have unsaved changes.", AutoSaveConfiguration.OFF, AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE, AutoSaveConfiguration.AFTER_DELAY), +- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.autoSaveDelay': { +- 'type': 'number', +- 'default': 1000, +- 'minimum': 0, +- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveDelay' }, "Controls the delay in milliseconds after which an editor with unsaved changes is saved automatically. Only applies when `#files.autoSave#` is set to `{0}`.", AutoSaveConfiguration.AFTER_DELAY), +- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.autoSaveWorkspaceFilesOnly': { +- 'type': 'boolean', +- 'default': false, +- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWorkspaceFilesOnly' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that are inside the opened workspace. Only applies when `#files.autoSave#` is enabled."), +- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.autoSaveWhenNoErrors': { +- 'type': 'boolean', +- 'default': false, +- 'markdownDescription': nls.localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'autoSaveWhenNoErrors' }, "When enabled, will limit [auto save](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) of editors to files that have no errors reported in them at the time the auto save is triggered. Only applies when `#files.autoSave#` is enabled."), +- scope: ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.watcherExclude': { +- 'type': 'object', +- 'patternProperties': { +- '.*': { 'type': 'boolean' } +- }, +- 'default': { '**/.git/objects/**': true, '**/.git/subtree-cache/**': true, '**/node_modules/*/**': true, '**/.hg/store/**': true }, +- 'markdownDescription': nls.localize('watcherExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from file watching. Paths can either be relative to the watched folder or absolute. Glob patterns are matched relative from the watched folder. When you experience the file watcher process consuming a lot of CPU, make sure to exclude large folders that are of less interest (such as build output folders)."), +- 'scope': ConfigurationScope.RESOURCE +- }, +- 'files.watcherInclude': { +- 'type': 'array', +- 'items': { +- 'type': 'string' +- }, +- 'default': [], +- 'description': nls.localize('watcherInclude', "Configure extra paths to watch for changes inside the workspace. By default, all workspace folders will be watched recursively, except for folders that are symbolic links. You can explicitly add absolute or relative paths to support watching folders that are symbolic links. Relative paths will be resolved to an absolute path using the currently opened workspace."), +- 'scope': ConfigurationScope.RESOURCE +- }, +- 'files.hotExit': hotExitConfiguration, +- 'files.defaultLanguage': { +- 'type': 'string', +- 'markdownDescription': nls.localize('defaultLanguage', "The default language identifier that is assigned to new files. If configured to `${activeEditorLanguage}`, will use the language identifier of the currently active text editor if any.") +- }, +- [FILES_READONLY_INCLUDE_CONFIG]: { +- 'type': 'object', +- 'patternProperties': { +- '.*': { 'type': 'boolean' } +- }, +- 'default': {}, +- 'markdownDescription': nls.localize('filesReadonlyInclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to mark as read-only. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. You can exclude matching paths via the `#files.readonlyExclude#` setting. Files from readonly file system providers will always be read-only independent of this setting."), +- 'scope': ConfigurationScope.RESOURCE +- }, +- [FILES_READONLY_EXCLUDE_CONFIG]: { +- 'type': 'object', +- 'patternProperties': { +- '.*': { 'type': 'boolean' } +- }, +- 'default': {}, +- 'markdownDescription': nls.localize('filesReadonlyExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) to exclude from being marked as read-only if they match as a result of the `#files.readonlyInclude#` setting. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths. Files from readonly file system providers will always be read-only independent of this setting."), +- 'scope': ConfigurationScope.RESOURCE +- }, +- [FILES_READONLY_FROM_PERMISSIONS_CONFIG]: { +- 'type': 'boolean', +- 'markdownDescription': nls.localize('filesReadonlyFromPermissions', "Marks files as read-only when their file permissions indicate as such. This can be overridden via `#files.readonlyInclude#` and `#files.readonlyExclude#` settings."), +- 'default': false +- }, +- 'files.restoreUndoStack': { +- 'type': 'boolean', +- 'description': nls.localize('files.restoreUndoStack', "Restore the undo stack when a file is reopened."), +- 'default': true +- }, +- 'files.saveConflictResolution': { +- 'type': 'string', +- 'enum': [ +- 'askUser', +- 'overwriteFileOnDisk' +- ], +- 'enumDescriptions': [ +- nls.localize('askUser', "Will refuse to save and ask for resolving the save conflict manually."), +- nls.localize('overwriteFileOnDisk', "Will resolve the save conflict by overwriting the file on disk with the changes in the editor.") +- ], +- 'description': nls.localize('files.saveConflictResolution', "A save conflict can occur when a file is saved to disk that was changed by another program in the meantime. To prevent data loss, the user is asked to compare the changes in the editor with the version on disk. This setting should only be changed if you frequently encounter save conflict errors and may result in data loss if used without caution."), +- 'default': 'askUser', +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE +- }, +- 'files.dialog.defaultPath': { +- 'type': 'string', +- 'pattern': '^((\\/|\\\\\\\\|[a-zA-Z]:\\\\).*)?$', // slash OR UNC-root OR drive-root OR undefined +- 'patternErrorMessage': nls.localize('defaultPathErrorMessage', "Default path for file dialogs must be an absolute path (e.g. C:\\\\myFolder or /myFolder)."), +- 'description': nls.localize('fileDialogDefaultPath', "Default path for file dialogs, overriding user's home path. Only used in the absence of a context-specific path, such as most recently opened file or folder."), +- 'scope': ConfigurationScope.MACHINE +- }, +- 'files.simpleDialog.enable': { +- 'type': 'boolean', +- 'description': nls.localize('files.simpleDialog.enable', "Enables the simple file dialog for opening and saving files and folders. The simple file dialog replaces the system file dialog when enabled."), +- 'default': false +- }, +- 'files.participants.timeout': { +- type: 'number', +- default: 60000, +- markdownDescription: nls.localize('files.participants.timeout', "Timeout in milliseconds after which file participants for create, rename, and delete are cancelled. Use `0` to disable participants."), +- } +- } +-}); +- +-configurationRegistry.registerConfiguration({ +- ...editorConfigurationBaseNode, +- properties: { +- 'editor.formatOnSave': { +- 'type': 'boolean', +- 'description': nls.localize('formatOnSave', "Format a file on save. A formatter must be available, the file must not be saved after delay, and the editor must not be shutting down."), +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, +- }, +- 'editor.formatOnSaveMode': { +- 'type': 'string', +- 'default': 'file', +- 'enum': [ +- 'file', +- 'modifications', +- 'modificationsIfAvailable' +- ], +- 'enumDescriptions': [ +- nls.localize({ key: 'everything', comment: ['This is the description of an option'] }, "Format the whole file."), +- nls.localize({ key: 'modification', comment: ['This is the description of an option'] }, "Format modifications (requires source control)."), +- nls.localize({ key: 'modificationIfAvailable', comment: ['This is the description of an option'] }, "Will attempt to format modifications only (requires source control). If source control can't be used, then the whole file will be formatted."), +- ], +- 'markdownDescription': nls.localize('formatOnSaveMode', "Controls if format on save formats the whole file or only modifications. Only applies when `#editor.formatOnSave#` is enabled."), +- 'scope': ConfigurationScope.LANGUAGE_OVERRIDABLE, +- }, +- } +-}); +- +-configurationRegistry.registerConfiguration({ +- 'id': 'explorer', +- 'order': 10, +- 'title': nls.localize('explorerConfigurationTitle', "File Explorer"), +- 'type': 'object', +- 'properties': { +- 'explorer.openEditors.visible': { +- 'type': 'number', +- 'description': nls.localize({ key: 'openEditorsVisible', comment: ['Open is an adjective'] }, "The initial maximum number of editors shown in the Open Editors pane. Exceeding this limit will show a scroll bar and allow resizing the pane to display more items."), +- 'default': 9, +- 'minimum': 1 +- }, +- 'explorer.openEditors.minVisible': { +- 'type': 'number', +- 'description': nls.localize({ key: 'openEditorsVisibleMin', comment: ['Open is an adjective'] }, "The minimum number of editor slots pre-allocated in the Open Editors pane. If set to 0 the Open Editors pane will dynamically resize based on the number of editors."), +- 'default': 0, +- 'minimum': 0 +- }, +- 'explorer.openEditors.sortOrder': { +- 'type': 'string', +- 'enum': ['editorOrder', 'alphabetical', 'fullPath'], +- 'description': nls.localize({ key: 'openEditorsSortOrder', comment: ['Open is an adjective'] }, "Controls the sorting order of editors in the Open Editors pane."), +- 'enumDescriptions': [ +- nls.localize('sortOrder.editorOrder', 'Editors are ordered in the same order editor tabs are shown.'), +- nls.localize('sortOrder.alphabetical', 'Editors are ordered alphabetically by tab name inside each editor group.'), +- nls.localize('sortOrder.fullPath', 'Editors are ordered alphabetically by full path inside each editor group.') +- ], +- 'default': 'editorOrder' +- }, +- 'explorer.autoReveal': { +- 'type': ['boolean', 'string'], +- 'enum': [true, false, 'focusNoScroll'], +- 'default': true, +- 'enumDescriptions': [ +- nls.localize('autoReveal.on', 'Files will be revealed and selected.'), +- nls.localize('autoReveal.off', 'Files will not be revealed and selected.'), +- nls.localize('autoReveal.focusNoScroll', 'Files will not be scrolled into view, but will still be focused.'), +- ], +- 'description': nls.localize('autoReveal', "Controls whether the Explorer should automatically reveal and select files when opening them.") +- }, +- 'explorer.autoRevealExclude': { +- 'type': 'object', +- 'markdownDescription': nls.localize('autoRevealExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) for excluding files and folders from being revealed and selected in the Explorer when they are opened. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths."), +- 'default': { '**/node_modules': true, '**/bower_components': true }, +- 'additionalProperties': { +- 'anyOf': [ +- { +- 'type': 'boolean', +- 'description': nls.localize('explorer.autoRevealExclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), +- }, +- { +- type: 'object', +- properties: { +- when: { +- type: 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) +- pattern: '\\w*\\$\\(basename\\)\\w*', +- default: '$(basename).ext', +- description: nls.localize('explorer.autoRevealExclude.when', 'Additional check on the siblings of a matching file. Use $(basename) as variable for the matching file name.') +- } +- } +- } +- ] +- } +- }, +- 'explorer.enableDragAndDrop': { +- 'type': 'boolean', +- 'description': nls.localize('enableDragAndDrop', "Controls whether the Explorer should allow to move files and folders via drag and drop. This setting only effects drag and drop from inside the Explorer."), +- 'default': true +- }, +- 'explorer.confirmDragAndDrop': { +- 'type': 'boolean', +- 'description': nls.localize('confirmDragAndDrop', "Controls whether the Explorer should ask for confirmation to move files and folders via drag and drop."), +- 'default': true +- }, +- 'explorer.confirmPasteNative': { +- 'type': 'boolean', +- 'description': nls.localize('confirmPasteNative', "Controls whether the Explorer should ask for confirmation when pasting native files and folders."), +- 'default': true +- }, +- 'explorer.confirmDelete': { +- 'type': 'boolean', +- 'description': nls.localize('confirmDelete', "Controls whether the Explorer should ask for confirmation when deleting a file via the trash."), +- 'default': true +- }, +- 'explorer.enableUndo': { +- 'type': 'boolean', +- 'description': nls.localize('enableUndo', "Controls whether the Explorer should support undoing file and folder operations."), +- 'default': true +- }, +- 'explorer.confirmUndo': { +- 'type': 'string', +- 'enum': [UndoConfirmLevel.Verbose, UndoConfirmLevel.Default, UndoConfirmLevel.Light], +- 'description': nls.localize('confirmUndo', "Controls whether the Explorer should ask for confirmation when undoing."), +- 'default': UndoConfirmLevel.Default, +- 'enumDescriptions': [ +- nls.localize('enableUndo.verbose', 'Explorer will prompt before all undo operations.'), +- nls.localize('enableUndo.default', 'Explorer will prompt before destructive undo operations.'), +- nls.localize('enableUndo.light', 'Explorer will not prompt before undo operations when focused.'), +- ], +- }, +- 'explorer.expandSingleFolderWorkspaces': { +- 'type': 'boolean', +- 'description': nls.localize('expandSingleFolderWorkspaces', "Controls whether the Explorer should expand multi-root workspaces containing only one folder during initialization"), +- 'default': true +- }, +- 'explorer.sortOrder': { +- 'type': 'string', +- 'enum': [SortOrder.Default, SortOrder.Mixed, SortOrder.FilesFirst, SortOrder.Type, SortOrder.Modified, SortOrder.FoldersNestsFiles], +- 'default': SortOrder.Default, +- 'enumDescriptions': [ +- nls.localize('sortOrder.default', 'Files and folders are sorted by their names. Folders are displayed before files.'), +- nls.localize('sortOrder.mixed', 'Files and folders are sorted by their names. Files are interwoven with folders.'), +- nls.localize('sortOrder.filesFirst', 'Files and folders are sorted by their names. Files are displayed before folders.'), +- nls.localize('sortOrder.type', 'Files and folders are grouped by extension type then sorted by their names. Folders are displayed before files.'), +- nls.localize('sortOrder.modified', 'Files and folders are sorted by last modified date in descending order. Folders are displayed before files.'), +- nls.localize('sortOrder.foldersNestsFiles', 'Files and folders are sorted by their names. Folders are displayed before files. Files with nested children are displayed before other files.') +- ], +- 'markdownDescription': nls.localize('sortOrder', "Controls the property-based sorting of files and folders in the Explorer. When `#explorer.fileNesting.enabled#` is enabled, also controls sorting of nested files.") +- }, +- 'explorer.sortOrderLexicographicOptions': { +- 'type': 'string', +- 'enum': [LexicographicOptions.Default, LexicographicOptions.Upper, LexicographicOptions.Lower, LexicographicOptions.Unicode], +- 'default': LexicographicOptions.Default, +- 'enumDescriptions': [ +- nls.localize('sortOrderLexicographicOptions.default', 'Uppercase and lowercase names are mixed together.'), +- nls.localize('sortOrderLexicographicOptions.upper', 'Uppercase names are grouped together before lowercase names.'), +- nls.localize('sortOrderLexicographicOptions.lower', 'Lowercase names are grouped together before uppercase names.'), +- nls.localize('sortOrderLexicographicOptions.unicode', 'Names are sorted in Unicode order.') +- ], +- 'description': nls.localize('sortOrderLexicographicOptions', "Controls the lexicographic sorting of file and folder names in the Explorer.") +- }, +- 'explorer.decorations.colors': { +- type: 'boolean', +- description: nls.localize('explorer.decorations.colors', "Controls whether file decorations should use colors."), +- default: true +- }, +- 'explorer.decorations.badges': { +- type: 'boolean', +- description: nls.localize('explorer.decorations.badges', "Controls whether file decorations should use badges."), +- default: true +- }, +- 'explorer.incrementalNaming': { +- 'type': 'string', +- enum: ['simple', 'smart', 'disabled'], +- enumDescriptions: [ +- nls.localize('simple', "Appends the word \"copy\" at the end of the duplicated name potentially followed by a number."), +- nls.localize('smart', "Adds a number at the end of the duplicated name. If some number is already part of the name, tries to increase that number."), +- nls.localize('disabled', "Disables incremental naming. If two files with the same name exist you will be prompted to overwrite the existing file.") +- ], +- description: nls.localize('explorer.incrementalNaming', "Controls which naming strategy to use when giving a new name to a duplicated Explorer item on paste."), +- default: 'simple' +- }, +- 'explorer.compactFolders': { +- 'type': 'boolean', +- 'description': nls.localize('compressSingleChildFolders', "Controls whether the Explorer should render folders in a compact form. In such a form, single child folders will be compressed in a combined tree element. Useful for Java package structures, for example."), +- 'default': true +- }, +- 'explorer.copyRelativePathSeparator': { +- 'type': 'string', +- 'enum': [ +- '/', +- '\\', +- 'auto' +- ], +- 'enumDescriptions': [ +- nls.localize('copyRelativePathSeparator.slash', "Use slash as path separation character."), +- nls.localize('copyRelativePathSeparator.backslash', "Use backslash as path separation character."), +- nls.localize('copyRelativePathSeparator.auto', "Uses operating system specific path separation character."), +- ], +- 'description': nls.localize('copyRelativePathSeparator', "The path separation character used when copying relative file paths."), +- 'default': 'auto' +- }, +- 'explorer.excludeGitIgnore': { +- type: 'boolean', +- markdownDescription: nls.localize('excludeGitignore', "Controls whether entries in .gitignore should be parsed and excluded from the Explorer. Similar to {0}.", '`#files.exclude#`'), +- default: false, +- scope: ConfigurationScope.RESOURCE +- }, +- 'explorer.fileNesting.enabled': { +- 'type': 'boolean', +- scope: ConfigurationScope.RESOURCE, +- 'markdownDescription': nls.localize('fileNestingEnabled', "Controls whether file nesting is enabled in the Explorer. File nesting allows for related files in a directory to be visually grouped together under a single parent file."), +- 'default': false, +- }, +- 'explorer.fileNesting.expand': { +- 'type': 'boolean', +- 'markdownDescription': nls.localize('fileNestingExpand', "Controls whether file nests are automatically expanded. {0} must be set for this to take effect.", '`#explorer.fileNesting.enabled#`'), +- 'default': true, +- }, +- 'explorer.fileNesting.patterns': { +- 'type': 'object', +- scope: ConfigurationScope.RESOURCE, +- 'markdownDescription': nls.localize('fileNestingPatterns', "Controls nesting of files in the Explorer. {0} must be set for this to take effect. Each __Item__ represents a parent pattern and may contain a single `*` character that matches any string. Each __Value__ represents a comma separated list of the child patterns that should be shown nested under a given parent. Child patterns may contain several special tokens:\n- `${capture}`: Matches the resolved value of the `*` from the parent pattern\n- `${basename}`: Matches the parent file's basename, the `file` in `file.ts`\n- `${extname}`: Matches the parent file's extension, the `ts` in `file.ts`\n- `${dirname}`: Matches the parent file's directory name, the `src` in `src/file.ts`\n- `*`: Matches any string, may only be used once per child pattern", '`#explorer.fileNesting.enabled#`'), +- patternProperties: { +- '^[^*]*\\*?[^*]*$': { +- markdownDescription: nls.localize('fileNesting.description', "Each key pattern may contain a single `*` character which will match any string."), +- type: 'string', +- pattern: '^([^,*]*\\*?[^,*]*)(, ?[^,*]*\\*?[^,*]*)*$', +- } +- }, +- additionalProperties: false, +- 'default': { +- '*.ts': '${capture}.js', +- '*.js': '${capture}.js.map, ${capture}.min.js, ${capture}.d.ts', +- '*.jsx': '${capture}.js', +- '*.tsx': '${capture}.ts', +- 'tsconfig.json': 'tsconfig.*.json', +- 'package.json': 'package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb', +- } +- } +- } +-}); +- +-UndoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { +- const undoRedoService = accessor.get(IUndoRedoService); +- const explorerService = accessor.get(IExplorerService); +- const configurationService = accessor.get(IConfigurationService); +- +- const explorerCanUndo = configurationService.getValue().explorer.enableUndo; +- if (explorerService.hasViewFocus() && undoRedoService.canUndo(UNDO_REDO_SOURCE) && explorerCanUndo) { +- undoRedoService.undo(UNDO_REDO_SOURCE); +- return true; +- } +- +- return false; +-}); +- +-RedoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { +- const undoRedoService = accessor.get(IUndoRedoService); +- const explorerService = accessor.get(IExplorerService); +- const configurationService = accessor.get(IConfigurationService); +- +- const explorerCanUndo = configurationService.getValue().explorer.enableUndo; +- if (explorerService.hasViewFocus() && undoRedoService.canRedo(UNDO_REDO_SOURCE) && explorerCanUndo) { +- undoRedoService.redo(UNDO_REDO_SOURCE); +- return true; +- } +- +- return false; +-}); +- +-ModesRegistry.registerLanguage({ +- id: BINARY_TEXT_FILE_MODE, +- aliases: ['Binary'], +- mimetypes: ['text/x-code-binary'] +-}); ++import './files.configuration.contribution'; ++import './files.editorPane.contribution'; ++import './files.fileEditorFactory.contribution'; ++import './files.explorer.contribution'; +diff --git a/src/vs/workbench/contrib/files/browser/files.editorPane.contribution.ts b/src/vs/workbench/contrib/files/browser/files.editorPane.contribution.ts +new file mode 100644 +index 00000000000..18a1975b685 +--- /dev/null ++++ b/src/vs/workbench/contrib/files/browser/files.editorPane.contribution.ts +@@ -0,0 +1,94 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import * as nls from 'vs/nls'; ++import { sep } from 'vs/base/common/path'; ++import { Registry } from 'vs/platform/registry/common/platform'; ++import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution, WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; ++import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; ++import { FILE_EDITOR_INPUT_ID, BINARY_TEXT_FILE_MODE } from 'vs/workbench/contrib/files/common/files'; ++import { TextFileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/textFileEditorTracker'; ++import { TextFileSaveErrorHandler } from 'vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler'; ++import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; ++import { BinaryFileEditor } from 'vs/workbench/contrib/files/browser/editors/binaryFileEditor'; ++import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; ++import { isWindows } from 'vs/base/common/platform'; ++import { IEditorPaneRegistry, EditorPaneDescriptor } from 'vs/workbench/browser/editor'; ++import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; ++import { ILabelService } from 'vs/platform/label/common/label'; ++import { Schemas } from 'vs/base/common/network'; ++import { WorkspaceWatcher } from 'vs/workbench/contrib/files/browser/workspaceWatcher'; ++import { DirtyFilesIndicator } from 'vs/workbench/contrib/files/common/dirtyFilesIndicator'; ++import { FileEditorInputSerializer, FileEditorWorkingCopyEditorHandler } from 'vs/workbench/contrib/files/browser/editors/fileEditorHandler'; ++import { ModesRegistry } from 'vs/editor/common/languages/modesRegistry'; ++import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; ++import './files.fileEditorFactory.contribution'; ++ ++class FileUriLabelContribution implements IWorkbenchContribution { ++ ++ static readonly ID = 'workbench.contrib.fileUriLabel'; ++ ++ constructor(@ILabelService labelService: ILabelService) { ++ labelService.registerFormatter({ ++ scheme: Schemas.file, ++ formatting: { ++ label: '${authority}${path}', ++ separator: sep, ++ tildify: !isWindows, ++ normalizeDriveLetter: isWindows, ++ authorityPrefix: sep + sep, ++ workspaceSuffix: '' ++ } ++ }); ++ } ++} ++// Register file editors ++ ++Registry.as(EditorExtensions.EditorPane).registerEditorPane( ++ EditorPaneDescriptor.create( ++ TextFileEditor, ++ TextFileEditor.ID, ++ nls.localize('textFileEditor', "Text File Editor") ++ ), ++ [ ++ new SyncDescriptor(FileEditorInput) ++ ] ++); ++ ++Registry.as(EditorExtensions.EditorPane).registerEditorPane( ++ EditorPaneDescriptor.create( ++ BinaryFileEditor, ++ BinaryFileEditor.ID, ++ nls.localize('binaryFileEditor', "Binary File Editor") ++ ), ++ [ ++ new SyncDescriptor(FileEditorInput) ++ ] ++); ++ ++// Register Editor Input Serializer & Handler ++Registry.as(EditorExtensions.EditorFactory).registerEditorSerializer(FILE_EDITOR_INPUT_ID, FileEditorInputSerializer); ++registerWorkbenchContribution2(FileEditorWorkingCopyEditorHandler.ID, FileEditorWorkingCopyEditorHandler, WorkbenchPhase.BlockRestore); ++ ++// Register Text File Editor Tracker ++registerWorkbenchContribution2(TextFileEditorTracker.ID, TextFileEditorTracker, WorkbenchPhase.BlockStartup); ++ ++// Register Text File Save Error Handler ++registerWorkbenchContribution2(TextFileSaveErrorHandler.ID, TextFileSaveErrorHandler, WorkbenchPhase.BlockStartup); ++ ++// Register uri display for file uris ++registerWorkbenchContribution2(FileUriLabelContribution.ID, FileUriLabelContribution, WorkbenchPhase.BlockStartup); ++ ++// Register Workspace Watcher ++Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(WorkspaceWatcher, LifecyclePhase.Restored); ++ ++// Register Dirty Files Indicator ++registerWorkbenchContribution2(DirtyFilesIndicator.ID, DirtyFilesIndicator, WorkbenchPhase.BlockStartup); ++ ++ModesRegistry.registerLanguage({ ++ id: BINARY_TEXT_FILE_MODE, ++ aliases: ['Binary'], ++ mimetypes: ['text/x-code-binary'] ++}); +diff --git a/src/vs/workbench/contrib/files/browser/files.explorer.contribution.ts b/src/vs/workbench/contrib/files/browser/files.explorer.contribution.ts +new file mode 100644 +index 00000000000..0ed00cb19e7 +--- /dev/null ++++ b/src/vs/workbench/contrib/files/browser/files.explorer.contribution.ts +@@ -0,0 +1,270 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; ++import * as nls from 'vs/nls'; ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; ++import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; ++import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; ++import { Registry } from 'vs/platform/registry/common/platform'; ++import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; ++import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; ++import { ExplorerService, UNDO_REDO_SOURCE } from 'vs/workbench/contrib/files/browser/explorerService'; ++import { ExplorerViewletViewsContribution } from 'vs/workbench/contrib/files/browser/explorerViewlet'; ++import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; ++import { IFilesConfiguration, LexicographicOptions, SortOrder, UndoConfirmLevel } from 'vs/workbench/contrib/files/common/files'; ++import './files.configuration.contribution'; ++import './files.editorPane.contribution'; ++import './files.fileEditorFactory.contribution'; ++ ++registerSingleton(IExplorerService, ExplorerService, InstantiationType.Delayed); ++ ++// Register Explorer views ++registerWorkbenchContribution2(ExplorerViewletViewsContribution.ID, ExplorerViewletViewsContribution, WorkbenchPhase.BlockStartup); ++ ++// Configuration ++const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); ++ ++configurationRegistry.registerConfiguration({ ++ 'id': 'explorer', ++ 'order': 10, ++ 'title': nls.localize('explorerConfigurationTitle', "File Explorer"), ++ 'type': 'object', ++ 'properties': { ++ 'explorer.openEditors.visible': { ++ 'type': 'number', ++ 'description': nls.localize({ key: 'openEditorsVisible', comment: ['Open is an adjective'] }, "The initial maximum number of editors shown in the Open Editors pane. Exceeding this limit will show a scroll bar and allow resizing the pane to display more items."), ++ 'default': 9, ++ 'minimum': 1 ++ }, ++ 'explorer.openEditors.minVisible': { ++ 'type': 'number', ++ 'description': nls.localize({ key: 'openEditorsVisibleMin', comment: ['Open is an adjective'] }, "The minimum number of editor slots pre-allocated in the Open Editors pane. If set to 0 the Open Editors pane will dynamically resize based on the number of editors."), ++ 'default': 0, ++ 'minimum': 0 ++ }, ++ 'explorer.openEditors.sortOrder': { ++ 'type': 'string', ++ 'enum': ['editorOrder', 'alphabetical', 'fullPath'], ++ 'description': nls.localize({ key: 'openEditorsSortOrder', comment: ['Open is an adjective'] }, "Controls the sorting order of editors in the Open Editors pane."), ++ 'enumDescriptions': [ ++ nls.localize('sortOrder.editorOrder', 'Editors are ordered in the same order editor tabs are shown.'), ++ nls.localize('sortOrder.alphabetical', 'Editors are ordered alphabetically by tab name inside each editor group.'), ++ nls.localize('sortOrder.fullPath', 'Editors are ordered alphabetically by full path inside each editor group.') ++ ], ++ 'default': 'editorOrder' ++ }, ++ 'explorer.autoReveal': { ++ 'type': ['boolean', 'string'], ++ 'enum': [true, false, 'focusNoScroll'], ++ 'default': true, ++ 'enumDescriptions': [ ++ nls.localize('autoReveal.on', 'Files will be revealed and selected.'), ++ nls.localize('autoReveal.off', 'Files will not be revealed and selected.'), ++ nls.localize('autoReveal.focusNoScroll', 'Files will not be scrolled into view, but will still be focused.'), ++ ], ++ 'description': nls.localize('autoReveal', "Controls whether the Explorer should automatically reveal and select files when opening them.") ++ }, ++ 'explorer.autoRevealExclude': { ++ 'type': 'object', ++ 'markdownDescription': nls.localize('autoRevealExclude', "Configure paths or [glob patterns](https://aka.ms/vscode-glob-patterns) for excluding files and folders from being revealed and selected in the Explorer when they are opened. Glob patterns are always evaluated relative to the path of the workspace folder unless they are absolute paths."), ++ 'default': { '**/node_modules': true, '**/bower_components': true }, ++ 'additionalProperties': { ++ 'anyOf': [ ++ { ++ 'type': 'boolean', ++ 'description': nls.localize('explorer.autoRevealExclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."), ++ }, ++ { ++ type: 'object', ++ properties: { ++ when: { ++ type: 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } }) ++ pattern: '\\w*\\$\\(basename\\)\\w*', ++ default: '$(basename).ext', ++ description: nls.localize('explorer.autoRevealExclude.when', 'Additional check on the siblings of a matching file. Use $(basename) as variable for the matching file name.') ++ } ++ } ++ } ++ ] ++ } ++ }, ++ 'explorer.enableDragAndDrop': { ++ 'type': 'boolean', ++ 'description': nls.localize('enableDragAndDrop', "Controls whether the Explorer should allow to move files and folders via drag and drop. This setting only effects drag and drop from inside the Explorer."), ++ 'default': true ++ }, ++ 'explorer.confirmDragAndDrop': { ++ 'type': 'boolean', ++ 'description': nls.localize('confirmDragAndDrop', "Controls whether the Explorer should ask for confirmation to move files and folders via drag and drop."), ++ 'default': true ++ }, ++ 'explorer.confirmPasteNative': { ++ 'type': 'boolean', ++ 'description': nls.localize('confirmPasteNative', "Controls whether the Explorer should ask for confirmation when pasting native files and folders."), ++ 'default': true ++ }, ++ 'explorer.confirmDelete': { ++ 'type': 'boolean', ++ 'description': nls.localize('confirmDelete', "Controls whether the Explorer should ask for confirmation when deleting a file via the trash."), ++ 'default': true ++ }, ++ 'explorer.enableUndo': { ++ 'type': 'boolean', ++ 'description': nls.localize('enableUndo', "Controls whether the Explorer should support undoing file and folder operations."), ++ 'default': true ++ }, ++ 'explorer.confirmUndo': { ++ 'type': 'string', ++ 'enum': [UndoConfirmLevel.Verbose, UndoConfirmLevel.Default, UndoConfirmLevel.Light], ++ 'description': nls.localize('confirmUndo', "Controls whether the Explorer should ask for confirmation when undoing."), ++ 'default': UndoConfirmLevel.Default, ++ 'enumDescriptions': [ ++ nls.localize('enableUndo.verbose', 'Explorer will prompt before all undo operations.'), ++ nls.localize('enableUndo.default', 'Explorer will prompt before destructive undo operations.'), ++ nls.localize('enableUndo.light', 'Explorer will not prompt before undo operations when focused.'), ++ ], ++ }, ++ 'explorer.expandSingleFolderWorkspaces': { ++ 'type': 'boolean', ++ 'description': nls.localize('expandSingleFolderWorkspaces', "Controls whether the Explorer should expand multi-root workspaces containing only one folder during initialization"), ++ 'default': true ++ }, ++ 'explorer.sortOrder': { ++ 'type': 'string', ++ 'enum': [SortOrder.Default, SortOrder.Mixed, SortOrder.FilesFirst, SortOrder.Type, SortOrder.Modified, SortOrder.FoldersNestsFiles], ++ 'default': SortOrder.Default, ++ 'enumDescriptions': [ ++ nls.localize('sortOrder.default', 'Files and folders are sorted by their names. Folders are displayed before files.'), ++ nls.localize('sortOrder.mixed', 'Files and folders are sorted by their names. Files are interwoven with folders.'), ++ nls.localize('sortOrder.filesFirst', 'Files and folders are sorted by their names. Files are displayed before folders.'), ++ nls.localize('sortOrder.type', 'Files and folders are grouped by extension type then sorted by their names. Folders are displayed before files.'), ++ nls.localize('sortOrder.modified', 'Files and folders are sorted by last modified date in descending order. Folders are displayed before files.'), ++ nls.localize('sortOrder.foldersNestsFiles', 'Files and folders are sorted by their names. Folders are displayed before files. Files with nested children are displayed before other files.') ++ ], ++ 'markdownDescription': nls.localize('sortOrder', "Controls the property-based sorting of files and folders in the Explorer. When `#explorer.fileNesting.enabled#` is enabled, also controls sorting of nested files.") ++ }, ++ 'explorer.sortOrderLexicographicOptions': { ++ 'type': 'string', ++ 'enum': [LexicographicOptions.Default, LexicographicOptions.Upper, LexicographicOptions.Lower, LexicographicOptions.Unicode], ++ 'default': LexicographicOptions.Default, ++ 'enumDescriptions': [ ++ nls.localize('sortOrderLexicographicOptions.default', 'Uppercase and lowercase names are mixed together.'), ++ nls.localize('sortOrderLexicographicOptions.upper', 'Uppercase names are grouped together before lowercase names.'), ++ nls.localize('sortOrderLexicographicOptions.lower', 'Lowercase names are grouped together before uppercase names.'), ++ nls.localize('sortOrderLexicographicOptions.unicode', 'Names are sorted in Unicode order.') ++ ], ++ 'description': nls.localize('sortOrderLexicographicOptions', "Controls the lexicographic sorting of file and folder names in the Explorer.") ++ }, ++ 'explorer.decorations.colors': { ++ type: 'boolean', ++ description: nls.localize('explorer.decorations.colors', "Controls whether file decorations should use colors."), ++ default: true ++ }, ++ 'explorer.decorations.badges': { ++ type: 'boolean', ++ description: nls.localize('explorer.decorations.badges', "Controls whether file decorations should use badges."), ++ default: true ++ }, ++ 'explorer.incrementalNaming': { ++ 'type': 'string', ++ enum: ['simple', 'smart', 'disabled'], ++ enumDescriptions: [ ++ nls.localize('simple', "Appends the word \"copy\" at the end of the duplicated name potentially followed by a number."), ++ nls.localize('smart', "Adds a number at the end of the duplicated name. If some number is already part of the name, tries to increase that number."), ++ nls.localize('disabled', "Disables incremental naming. If two files with the same name exist you will be prompted to overwrite the existing file.") ++ ], ++ description: nls.localize('explorer.incrementalNaming', "Controls which naming strategy to use when giving a new name to a duplicated Explorer item on paste."), ++ default: 'simple' ++ }, ++ 'explorer.compactFolders': { ++ 'type': 'boolean', ++ 'description': nls.localize('compressSingleChildFolders', "Controls whether the Explorer should render folders in a compact form. In such a form, single child folders will be compressed in a combined tree element. Useful for Java package structures, for example."), ++ 'default': true ++ }, ++ 'explorer.copyRelativePathSeparator': { ++ 'type': 'string', ++ 'enum': [ ++ '/', ++ '\\', ++ 'auto' ++ ], ++ 'enumDescriptions': [ ++ nls.localize('copyRelativePathSeparator.slash', "Use slash as path separation character."), ++ nls.localize('copyRelativePathSeparator.backslash', "Use backslash as path separation character."), ++ nls.localize('copyRelativePathSeparator.auto', "Uses operating system specific path separation character."), ++ ], ++ 'description': nls.localize('copyRelativePathSeparator', "The path separation character used when copying relative file paths."), ++ 'default': 'auto' ++ }, ++ 'explorer.excludeGitIgnore': { ++ type: 'boolean', ++ markdownDescription: nls.localize('excludeGitignore', "Controls whether entries in .gitignore should be parsed and excluded from the Explorer. Similar to {0}.", '`#files.exclude#`'), ++ default: false, ++ scope: ConfigurationScope.RESOURCE ++ }, ++ 'explorer.fileNesting.enabled': { ++ 'type': 'boolean', ++ scope: ConfigurationScope.RESOURCE, ++ 'markdownDescription': nls.localize('fileNestingEnabled', "Controls whether file nesting is enabled in the Explorer. File nesting allows for related files in a directory to be visually grouped together under a single parent file."), ++ 'default': false, ++ }, ++ 'explorer.fileNesting.expand': { ++ 'type': 'boolean', ++ 'markdownDescription': nls.localize('fileNestingExpand', "Controls whether file nests are automatically expanded. {0} must be set for this to take effect.", '`#explorer.fileNesting.enabled#`'), ++ 'default': true, ++ }, ++ 'explorer.fileNesting.patterns': { ++ 'type': 'object', ++ scope: ConfigurationScope.RESOURCE, ++ 'markdownDescription': nls.localize('fileNestingPatterns', "Controls nesting of files in the Explorer. {0} must be set for this to take effect. Each __Item__ represents a parent pattern and may contain a single `*` character that matches any string. Each __Value__ represents a comma separated list of the child patterns that should be shown nested under a given parent. Child patterns may contain several special tokens:\n- `${capture}`: Matches the resolved value of the `*` from the parent pattern\n- `${basename}`: Matches the parent file's basename, the `file` in `file.ts`\n- `${extname}`: Matches the parent file's extension, the `ts` in `file.ts`\n- `${dirname}`: Matches the parent file's directory name, the `src` in `src/file.ts`\n- `*`: Matches any string, may only be used once per child pattern", '`#explorer.fileNesting.enabled#`'), ++ patternProperties: { ++ '^[^*]*\\*?[^*]*$': { ++ markdownDescription: nls.localize('fileNesting.description', "Each key pattern may contain a single `*` character which will match any string."), ++ type: 'string', ++ pattern: '^([^,*]*\\*?[^,*]*)(, ?[^,*]*\\*?[^,*]*)*$', ++ } ++ }, ++ additionalProperties: false, ++ 'default': { ++ '*.ts': '${capture}.js', ++ '*.js': '${capture}.js.map, ${capture}.min.js, ${capture}.d.ts', ++ '*.jsx': '${capture}.js', ++ '*.tsx': '${capture}.ts', ++ 'tsconfig.json': 'tsconfig.*.json', ++ 'package.json': 'package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb', ++ } ++ } ++ } ++}); ++ ++UndoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { ++ const undoRedoService = accessor.get(IUndoRedoService); ++ const explorerService = accessor.get(IExplorerService); ++ const configurationService = accessor.get(IConfigurationService); ++ ++ const explorerCanUndo = configurationService.getValue().explorer.enableUndo; ++ if (explorerService.hasViewFocus() && undoRedoService.canUndo(UNDO_REDO_SOURCE) && explorerCanUndo) { ++ undoRedoService.undo(UNDO_REDO_SOURCE); ++ return true; ++ } ++ ++ return false; ++}); ++ ++RedoCommand.addImplementation(110, 'explorer', (accessor: ServicesAccessor) => { ++ const undoRedoService = accessor.get(IUndoRedoService); ++ const explorerService = accessor.get(IExplorerService); ++ const configurationService = accessor.get(IConfigurationService); ++ ++ const explorerCanUndo = configurationService.getValue().explorer.enableUndo; ++ if (explorerService.hasViewFocus() && undoRedoService.canRedo(UNDO_REDO_SOURCE) && explorerCanUndo) { ++ undoRedoService.redo(UNDO_REDO_SOURCE); ++ return true; ++ } ++ ++ return false; ++}); +diff --git a/src/vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution.ts b/src/vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution.ts +new file mode 100644 +index 00000000000..2f31d6a7984 +--- /dev/null ++++ b/src/vs/workbench/contrib/files/browser/files.fileEditorFactory.contribution.ts +@@ -0,0 +1,23 @@ ++/*--------------------------------------------------------------------------------------------- ++ * Copyright (c) Microsoft Corporation. All rights reserved. ++ * Licensed under the MIT License. See License.txt in the project root for license information. ++ *--------------------------------------------------------------------------------------------*/ ++ ++import { Registry } from 'vs/platform/registry/common/platform'; ++import { EditorExtensions, IEditorFactoryRegistry, IFileEditorInput } from 'vs/workbench/common/editor'; ++import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; ++import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files'; ++ ++// Register default file input factory ++Registry.as(EditorExtensions.EditorFactory).registerFileEditorFactory({ ++ ++ typeId: FILE_EDITOR_INPUT_ID, ++ ++ createFileEditor: (resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents, instantiationService): IFileEditorInput => { ++ return instantiationService.createInstance(FileEditorInput, resource, preferredResource, preferredName, preferredDescription, preferredEncoding, preferredLanguageId, preferredContents); ++ }, ++ ++ isFileEditor: (obj): obj is IFileEditorInput => { ++ return obj instanceof FileEditorInput; ++ } ++}); +-- +2.34.1 + diff --git a/vscode-paches/0036-fix-replace-map-by-forEach.patch b/vscode-paches/0036-fix-replace-map-by-forEach.patch new file mode 100644 index 00000000..983f9fcc --- /dev/null +++ b/vscode-paches/0036-fix-replace-map-by-forEach.patch @@ -0,0 +1,39 @@ +From f69bbad5cdfbfdd31534f6e7d30e01c7599f233b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:50:13 +0100 +Subject: [PATCH 36/58] fix: replace map by forEach + +--- + src/vs/workbench/browser/parts/compositeBar.ts | 2 +- + src/vs/workbench/browser/parts/views/viewPaneContainer.ts | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts +index 76d6c0c1ee4..3060baec73a 100644 +--- a/src/vs/workbench/browser/parts/compositeBar.ts ++++ b/src/vs/workbench/browser/parts/compositeBar.ts +@@ -476,7 +476,7 @@ export class CompositeBar extends Widget implements ICompositeBar { + // Compute sizes only if visible. Otherwise the size measurment would be computed wrongly. + const currentItemsLength = compositeSwitcherBar.viewItems.length; + compositeSwitcherBar.push(items.map(composite => composite.activityAction)); +- items.map((composite, index) => this.compositeSizeInBar.set(composite.id, this.options.orientation === ActionsOrientation.VERTICAL ++ items.forEach((composite, index) => this.compositeSizeInBar.set(composite.id, this.options.orientation === ActionsOrientation.VERTICAL + ? compositeSwitcherBar.getHeight(currentItemsLength + index) + : compositeSwitcherBar.getWidth(currentItemsLength + index) + )); +diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +index f575fa95242..e0fc917b228 100644 +--- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts ++++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +@@ -679,7 +679,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { + } + + this.panes.filter(view => view.isVisible() !== visible) +- .map((view) => view.setVisible(visible)); ++ .forEach((view) => view.setVisible(visible)); + } + + isVisible(): boolean { +-- +2.34.1 + diff --git a/vscode-paches/0037-feat-only-apply-style-on-specific-class.patch b/vscode-paches/0037-feat-only-apply-style-on-specific-class.patch new file mode 100644 index 00000000..e140ec05 --- /dev/null +++ b/vscode-paches/0037-feat-only-apply-style-on-specific-class.patch @@ -0,0 +1,242 @@ +From ad4c750fef43f836355a0cd9194a8cdacc77f247 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:51:04 +0100 +Subject: [PATCH 37/58] feat: only apply style on specific class + +--- + src/vs/workbench/browser/media/style.css | 134 ++++++++++------------- + 1 file changed, 58 insertions(+), 76 deletions(-) + +diff --git a/src/vs/workbench/browser/media/style.css b/src/vs/workbench/browser/media/style.css +index db4862c7427..63c0d15ad5e 100644 +--- a/src/vs/workbench/browser/media/style.css ++++ b/src/vs/workbench/browser/media/style.css +@@ -9,56 +9,38 @@ + + /* Font Families (with CJK support) */ + +-.mac { font-family: -apple-system, BlinkMacSystemFont, sans-serif; } +-.mac:lang(zh-Hans) { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; } +-.mac:lang(zh-Hant) { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; } +-.mac:lang(ja) { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; } +-.mac:lang(ko) { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; } +- +-.windows { font-family: "Segoe WPC", "Segoe UI", sans-serif; } +-.windows:lang(zh-Hans) { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; } +-.windows:lang(zh-Hant) { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; } +-.windows:lang(ja) { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; } +-.windows:lang(ko) { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; } ++.mac .monaco-workbench-part{ font-family: -apple-system, BlinkMacSystemFont, sans-serif; } ++.mac:lang(zh-Hans) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", sans-serif; } ++.mac:lang(zh-Hant) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; } ++.mac:lang(ja) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "Hiragino Kaku Gothic Pro", sans-serif; } ++.mac:lang(ko) .monaco-workbench-part { font-family: -apple-system, BlinkMacSystemFont, "Nanum Gothic", "Apple SD Gothic Neo", "AppleGothic", sans-serif; } ++ ++.windows .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", sans-serif; } ++.windows:lang(zh-Hans) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Microsoft YaHei", sans-serif; } ++.windows:lang(zh-Hant) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Microsoft Jhenghei", sans-serif; } ++.windows:lang(ja) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Yu Gothic UI", "Meiryo UI", sans-serif; } ++.windows:lang(ko) .monaco-workbench-part { font-family: "Segoe WPC", "Segoe UI", "Malgun Gothic", "Dotom", sans-serif; } + + /* Linux: add `system-ui` as first font and not `Ubuntu` to allow other distribution pick their standard OS font */ +-.linux { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; } +-.linux:lang(zh-Hans) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; } +-.linux:lang(zh-Hant) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; } +-.linux:lang(ja) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; } +-.linux:lang(ko) { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; } ++.linux .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", sans-serif; } ++.linux:lang(zh-Hans) .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans SC", "Source Han Sans CN", "Source Han Sans", sans-serif; } ++.linux:lang(zh-Hant) .monaco-workbench-partt { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans TC", "Source Han Sans TW", "Source Han Sans", sans-serif; } ++.linux:lang(ja) .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans J", "Source Han Sans JP", "Source Han Sans", sans-serif; } ++.linux:lang(ko) .monaco-workbench-part { font-family: system-ui, "Ubuntu", "Droid Sans", "Source Han Sans K", "Source Han Sans JR", "Source Han Sans", "UnDotum", "FBaekmuk Gulim", sans-serif; } + +-.mac { --monaco-monospace-font: "SF Mono", Monaco, Menlo, Courier, monospace; } +-.windows { --monaco-monospace-font: Consolas, "Courier New", monospace; } +-.linux { --monaco-monospace-font: "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace; } ++.mac .monaco-workbench-part { --monaco-monospace-font: "SF Mono", Monaco, Menlo, Courier, monospace; } ++.windows .monaco-workbench-part { --monaco-monospace-font: Consolas, "Courier New", monospace; } ++.linux .monaco-workbench-part { --monaco-monospace-font: "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace; } + + /* Global Styles */ + +-body { +- height: 100%; +- width: 100%; +- margin: 0; +- padding: 0; +- overflow: hidden; +- font-size: 11px; +- user-select: none; +- -webkit-user-select: none; +-} +- +-body.web { +- position: fixed; /* prevent bounce effect */ +-} +- +-.monaco-workbench { ++.monaco-workbench-part { + font-size: 13px; + line-height: 1.4em; +- position: relative; +- z-index: 1; +- overflow: hidden; + color: var(--vscode-foreground); + } + +-.monaco-workbench.web { ++.monaco-workbench.web .monaco-workbench-part, .monaco-workbench-part.web { + touch-action: none; /* Disable browser handling of all panning and zooming gestures. Removes 300ms touch delay. */ + } + +@@ -79,65 +61,65 @@ body.web { + border: 0; + } + +-.monaco-workbench label { ++.monaco-workbench-part label { + cursor: pointer; + } + +-.monaco-workbench a { ++.monaco-workbench-part a { + text-decoration: none; + } + +-.monaco-workbench.hc-black p > a, +-.monaco-workbench.hc-light p > a { ++.monaco-workbench.hc-black .monaco-workbench-part p > a, ++.monaco-workbench.hc-light .monaco-workbench-part p > a { + text-decoration: underline !important; + } + +-.monaco-workbench a:active { ++.monaco-workbench-part a:active { + color: inherit; + background-color: inherit; + } + +-.monaco-workbench a.plain { ++.monaco-workbench-part a.plain { + color: inherit; + text-decoration: none; + } + +-.monaco-workbench a.plain:hover, +-.monaco-workbench a.plain.hover { ++.monaco-workbench-part a.plain:hover, ++.monaco-workbench-part a.plain.hover { + color: inherit; + text-decoration: none; + } + +-.monaco-workbench input { ++.monaco-workbench-part input { + color: inherit; + font-family: inherit; + font-size: 100%; + } + +-.monaco-workbench input::placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench input::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench input::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench-part input::placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench-part input::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench-part input::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } + +-.monaco-workbench textarea::placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench textarea::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } +-.monaco-workbench textarea::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench-part textarea::placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench-part textarea::-webkit-input-placeholder { color: var(--vscode-input-placeholderForeground); } ++.monaco-workbench-part textarea::-moz-placeholder { color: var(--vscode-input-placeholderForeground); } + +-.monaco-workbench .pointer { ++.monaco-workbench-part .pointer { + cursor: pointer; + } + +-.monaco-workbench.mac.monaco-font-aliasing-antialiased { ++.monaco-workbench.mac.monaco-font-aliasing-antialiased.monaco-workbench-part, .monaco-workbench.mac.monaco-font-aliasing-antialiased .monaco-workbench-part { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + +-.monaco-workbench.mac.monaco-font-aliasing-none { ++.monaco-workbench.mac.monaco-font-aliasing-none.monaco-workbench-part, .monaco-workbench.mac.monaco-font-aliasing-none .monaco-workbench-part { + -webkit-font-smoothing: none; + -moz-osx-font-smoothing: unset; + } + + @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { +- .monaco-workbench.mac.monaco-font-aliasing-auto { ++ .monaco-workbench.mac.monaco-font-aliasing-auto.monaco-workbench-part, .monaco-workbench.mac.monaco-font-aliasing-auto .monaco-workbench-part { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } +@@ -172,7 +154,7 @@ body.web { + + /* Custom Dropdown (select) Arrows */ + +-.monaco-workbench select { ++.monaco-workbench-part select { + font-family: inherit; + appearance: none; + -webkit-appearance: none; +@@ -202,16 +184,16 @@ body.web { + + /* Keyboard Focus Indication Styles */ + +-.monaco-workbench [tabindex="0"]:focus, +-.monaco-workbench [tabindex="-1"]:focus, +-.monaco-workbench .synthetic-focus, +-.monaco-workbench select:focus, +-.monaco-workbench input[type="button"]:focus, +-.monaco-workbench input[type="text"]:focus, +-.monaco-workbench button:focus, +-.monaco-workbench textarea:focus, +-.monaco-workbench input[type="search"]:focus, +-.monaco-workbench input[type="checkbox"]:focus { ++.monaco-workbench-part [tabindex="0"]:focus, ++.monaco-workbench-part [tabindex="-1"]:focus, ++.monaco-workbench-part .synthetic-focus, ++.monaco-workbench-part select:focus, ++.monaco-workbench-part input[type="button"]:focus, ++.monaco-workbench-part input[type="text"]:focus, ++.monaco-workbench-part button:focus, ++.monaco-workbench-part textarea:focus, ++.monaco-workbench-part input[type="search"]:focus, ++.monaco-workbench-part input[type="checkbox"]:focus { + outline-width: 1px; + outline-style: solid; + outline-offset: -1px; +@@ -224,19 +206,19 @@ body.web { + background: transparent; /* Search input focus fix when in high contrast */ + } + +-.monaco-workbench input[type="checkbox"]:focus { ++.monaco-workbench-part input[type="checkbox"]:focus { + outline-offset: 2px; + } + +-.monaco-workbench [tabindex="0"]:active, +-.monaco-workbench [tabindex="-1"]:active, +-.monaco-workbench select:active, +-.monaco-workbench input[type="button"]:active, +-.monaco-workbench input[type="checkbox"]:active { ++.monaco-workbench-part [tabindex="0"]:active, ++.monaco-workbench-part [tabindex="-1"]:active, ++.monaco-workbench-part select:active, ++.monaco-workbench-part input[type="button"]:active, ++.monaco-workbench-part input[type="checkbox"]:active { + outline: 0 !important; /* fixes some flashing outlines from showing up when clicking */ + } + +-.monaco-workbench.mac select:focus { ++.monaco-workbench.mac.monaco-workbench-part select:focus, .monaco-workbench.mac .monaco-workbench-part select:focus { + border-color: transparent; /* outline is a square, but border has a radius, so we avoid this glitch when focused (https://github.com/microsoft/vscode/issues/26045) */ + } + +-- +2.34.1 + diff --git a/vscode-paches/0038-fix-fix-fullscreen-layout.patch b/vscode-paches/0038-fix-fix-fullscreen-layout.patch new file mode 100644 index 00000000..a554b19e --- /dev/null +++ b/vscode-paches/0038-fix-fix-fullscreen-layout.patch @@ -0,0 +1,29 @@ +From 3f2f0af6a250da6c08868015c377404df5c40367 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 17:51:27 +0100 +Subject: [PATCH 38/58] fix: fix fullscreen layout + +--- + src/vs/workbench/browser/layout.ts | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts +index 4ee25602224..b563b949fb7 100644 +--- a/src/vs/workbench/browser/layout.ts ++++ b/src/vs/workbench/browser/layout.ts +@@ -1541,8 +1541,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi + + layout(): void { + if (!this.disposed) { +- this._mainContainerDimension = getClientArea(this.parent); +- this.logService.trace(`Layout#layout, height: ${this._mainContainerDimension.height}, width: ${this._mainContainerDimension.width}`); ++ this._mainContainerDimension = getClientArea(this.state.runtime.mainWindowFullscreen ? ++ mainWindow.document.body : // in fullscreen mode, make sure to use element because ++ this.parent // in that case the workbench will span the entire site ++ ); this.logService.trace(`Layout#layout, height: ${this._mainContainerDimension.height}, width: ${this._mainContainerDimension.width}`); + + position(this.mainContainer, 0, 0, 0, 0, 'relative'); + size(this.mainContainer, this._mainContainerDimension.width, this._mainContainerDimension.height); +-- +2.34.1 + diff --git a/vscode-paches/0039-fix-do-not-call-FileAccess.asBrowserUri-at-the-root-.patch b/vscode-paches/0039-fix-do-not-call-FileAccess.asBrowserUri-at-the-root-.patch new file mode 100644 index 00000000..472cf309 --- /dev/null +++ b/vscode-paches/0039-fix-do-not-call-FileAccess.asBrowserUri-at-the-root-.patch @@ -0,0 +1,98 @@ +From 82d7b76be9be6858c800ce69e4c972de985e45e5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:15:15 +0100 +Subject: [PATCH 39/58] fix: do not call FileAccess.asBrowserUri at the root of + the module + +to be able to register the file before +--- + .../extensions/browser/abstractRuntimeExtensionsEditor.ts | 6 +++--- + .../extensions/browser/extensionsWorkbenchService.ts | 4 ++-- + .../welcomeGettingStarted/browser/gettingStartedService.ts | 4 ++-- + .../extensionManagement/common/extensionManagement.ts | 2 +- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +index 991a3df035c..cb0b0288249 100644 +--- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts ++++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts +@@ -39,7 +39,7 @@ import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/r + import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; + import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; + import { Extensions, IExtensionFeaturesManagementService, IExtensionFeaturesRegistry } from 'vs/workbench/services/extensionManagement/common/extensionFeatures'; +-import { DefaultIconPath, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; ++import { getDefaultIconPath, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; + import { LocalWebWorkerRunningLocation } from 'vs/workbench/services/extensions/common/extensionRunningLocation'; + import { IExtensionHostProfile, IExtensionService, IExtensionsStatus } from 'vs/workbench/services/extensions/common/extensions'; + +@@ -271,8 +271,8 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane { + + data.root.classList.toggle('odd', index % 2 === 1); + +- data.elementDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = element.marketplaceInfo?.iconUrlFallback || DefaultIconPath, { once: true })); +- data.icon.src = element.marketplaceInfo?.iconUrl || DefaultIconPath; ++ data.elementDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = element.marketplaceInfo?.iconUrlFallback || getDefaultIconPath(), { once: true })); ++ data.icon.src = element.marketplaceInfo?.iconUrl || getDefaultIconPath(); + + if (!data.icon.complete) { + data.icon.style.visibility = 'hidden'; +diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +index fa11076ab65..dbca12bf6aa 100644 +--- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts ++++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +@@ -17,7 +17,7 @@ import { + InstallExtensionEvent, DidUninstallExtensionEvent, InstallOperation, InstallOptions, WEB_EXTENSION_TAG, InstallExtensionResult, + IExtensionsControlManifest, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions, IDeprecationInfo, isTargetPlatformCompatible, InstallExtensionInfo, EXTENSION_IDENTIFIER_REGEX + } from 'vs/platform/extensionManagement/common/extensionManagement'; +-import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, DefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; ++import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, getDefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; + import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, groupByExtension, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; + import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; + import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +@@ -205,7 +205,7 @@ export class Extension implements IExtension { + } + } + } +- return DefaultIconPath; ++ return getDefaultIconPath(); + } + + get repository(): string | undefined { +diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts +index 8a068851f28..eb4ed86bd31 100644 +--- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts ++++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts +@@ -33,7 +33,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; + import { checkGlobFileExists } from 'vs/workbench/services/extensions/common/workspaceContains'; + import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; + import { CancellationTokenSource } from 'vs/base/common/cancellation'; +-import { DefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; ++import { getDefaultIconPath } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; + + export const HasMultipleNewFileEntries = new RawContextKey('hasMultipleNewFileEntries', false); + +@@ -396,7 +396,7 @@ export class WalkthroughsService extends Disposable implements IWalkthroughsServ + type: 'image', + path: iconStr + ? FileAccess.uriToBrowserUri(joinPath(extension.extensionLocation, iconStr)).toString(true) +- : DefaultIconPath ++ : getDefaultIconPath() + }, + when: ContextKeyExpr.deserialize(override ?? walkthrough.when) ?? ContextKeyExpr.true(), + } as const; +diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts +index 362e485948a..50f5a5f175d 100644 +--- a/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts ++++ b/src/vs/workbench/services/extensionManagement/common/extensionManagement.ts +@@ -39,7 +39,7 @@ export interface IExtensionManagementServerService { + getExtensionInstallLocation(extension: IExtension): ExtensionInstallLocation | null; + } + +-export const DefaultIconPath = FileAccess.asBrowserUri('vs/workbench/services/extensionManagement/common/media/defaultIcon.png').toString(true); ++export const getDefaultIconPath = () => FileAccess.asBrowserUri('vs/workbench/services/extensionManagement/common/media/defaultIcon.png').toString(true); + + export type InstallExtensionOnServerEvent = InstallExtensionEvent & { server: IExtensionManagementServer }; + export type UninstallExtensionOnServerEvent = UninstallExtensionEvent & { server: IExtensionManagementServer }; +-- +2.34.1 + diff --git a/vscode-paches/0040-fixup-fixup-fix-replace-amd-imports-by-regular-esm-d.patch b/vscode-paches/0040-fixup-fixup-fix-replace-amd-imports-by-regular-esm-d.patch new file mode 100644 index 00000000..ac0fa7ab --- /dev/null +++ b/vscode-paches/0040-fixup-fixup-fix-replace-amd-imports-by-regular-esm-d.patch @@ -0,0 +1,61 @@ +From ee6ef65a4e8f5158d374d305861d09194a5580aa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:15:38 +0100 +Subject: [PATCH 40/58] fixup! fixup! fix: replace amd imports by regular esm + dynamic imports + +--- + src/vs/workbench/services/textfile/common/encoding.ts | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/vs/workbench/services/textfile/common/encoding.ts b/src/vs/workbench/services/textfile/common/encoding.ts +index ad67fb4f422..fadf86cece5 100644 +--- a/src/vs/workbench/services/textfile/common/encoding.ts ++++ b/src/vs/workbench/services/textfile/common/encoding.ts +@@ -5,7 +5,6 @@ + + import { Readable, ReadableStream, newWriteableStream, listenStream } from 'vs/base/common/stream'; + import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer'; +-import { importAMDNodeModule } from 'vs/amdX'; + import { CancellationTokenSource } from 'vs/base/common/cancellation'; + + export const UTF8 = 'utf8'; +@@ -80,7 +79,7 @@ class DecoderStream implements IDecoderStream { + static async create(encoding: string): Promise { + let decoder: IDecoderStream | undefined = undefined; + if (encoding !== UTF8) { +- const iconv = await importAMDNodeModule('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js'); ++ const iconv = await import('@vscode/iconv-lite-umd'); + decoder = iconv.getDecoder(toNodeEncoding(encoding)); + } else { + const utf8TextDecoder = new TextDecoder(); +@@ -213,7 +212,7 @@ export function toDecodeStream(source: VSBufferReadableStream, options: IDecodeS + } + + export async function toEncodeReadable(readable: Readable, encoding: string, options?: { addBOM?: boolean }): Promise { +- const iconv = await importAMDNodeModule('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js'); ++ const iconv = await import('@vscode/iconv-lite-umd'); + const encoder = iconv.getEncoder(toNodeEncoding(encoding), options); + + let bytesWritten = false; +@@ -262,7 +261,7 @@ export async function toEncodeReadable(readable: Readable, encoding: str + } + + export async function encodingExists(encoding: string): Promise { +- const iconv = await importAMDNodeModule('@vscode/iconv-lite-umd', 'lib/iconv-lite-umd.js'); ++ const iconv = await import('@vscode/iconv-lite-umd'); + + return iconv.encodingExists(toNodeEncoding(encoding)); + } +@@ -318,7 +317,7 @@ const IGNORE_ENCODINGS = ['ascii', 'utf-16', 'utf-32']; + * Guesses the encoding from buffer. + */ + async function guessEncodingByBuffer(buffer: VSBuffer): Promise { +- const jschardet = await importAMDNodeModule('jschardet', 'dist/jschardet.min.js'); ++ const jschardet = await import('jschardet'); + + // ensure to limit buffer for guessing due to https://github.com/aadsm/jschardet/issues/53 + const limitedBuffer = buffer.slice(0, AUTO_ENCODING_GUESS_MAX_BYTES); +-- +2.34.1 + diff --git a/vscode-paches/0041-cleanup-remove-some-checks-and-warnings.patch b/vscode-paches/0041-cleanup-remove-some-checks-and-warnings.patch new file mode 100644 index 00000000..341868a7 --- /dev/null +++ b/vscode-paches/0041-cleanup-remove-some-checks-and-warnings.patch @@ -0,0 +1,74 @@ +From 427d7fa82ca2ae1da2b8c6784552bebb3510a435 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:16:29 +0100 +Subject: [PATCH 41/58] cleanup: remove some checks and warnings + +--- + .../auxiliaryWindow/browser/auxiliaryWindowService.ts | 7 ------- + .../extensions/browser/webWorkerExtensionHost.ts | 2 -- + .../services/textMate/common/TMScopeRegistry.ts | 11 ----------- + 3 files changed, 20 deletions(-) + +diff --git a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts +index ce6f32b0914..4fe4fb39bd7 100644 +--- a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts ++++ b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts +@@ -302,13 +302,6 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili + } + + protected patchMethods(auxiliaryWindow: CodeWindow): void { +- +- // Disallow `createElement` because it would create +- // HTML Elements in the "wrong" context and break +- // code that does "instanceof HTMLElement" etc. +- auxiliaryWindow.document.createElement = function () { +- throw new Error('Not allowed to create elements in child window JavaScript context. Always use the main window so that "xyz instanceof HTMLElement" continues to work.'); +- }; + } + + private applyMeta(auxiliaryWindow: CodeWindow): void { +diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +index a5f5e42eddd..7d462411a9c 100644 +--- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts ++++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +@@ -111,8 +111,6 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost + res.searchParams.set('salt', stableOriginUUID); + return res.toString(); + } +- +- console.warn(`The web worker extension host is started in a same-origin iframe!`); + } + + const relativeExtensionHostIframeSrc = FileAccess.asBrowserUri(iframeModulePath); +diff --git a/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts b/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts +index a1a0779371e..18ca6d1b496 100644 +--- a/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts ++++ b/src/vs/workbench/services/textMate/common/TMScopeRegistry.ts +@@ -3,7 +3,6 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import * as resources from 'vs/base/common/resources'; + import { URI } from 'vs/base/common/uri'; + import { LanguageId, StandardTokenType } from 'vs/editor/common/encodedTokenAttributes'; + +@@ -40,16 +39,6 @@ export class TMScopeRegistry { + } + + public register(def: IValidGrammarDefinition): void { +- if (this._scopeNameToLanguageRegistration[def.scopeName]) { +- const existingRegistration = this._scopeNameToLanguageRegistration[def.scopeName]; +- if (!resources.isEqual(existingRegistration.location, def.location)) { +- console.warn( +- `Overwriting grammar scope name to file mapping for scope ${def.scopeName}.\n` + +- `Old grammar file: ${existingRegistration.location.toString()}.\n` + +- `New grammar file: ${def.location.toString()}` +- ); +- } +- } + this._scopeNameToLanguageRegistration[def.scopeName] = def; + } + +-- +2.34.1 + diff --git a/vscode-paches/0042-fixup-feat-export-some-classes-and-make-some-methods.patch b/vscode-paches/0042-fixup-feat-export-some-classes-and-make-some-methods.patch new file mode 100644 index 00000000..4c19fea0 --- /dev/null +++ b/vscode-paches/0042-fixup-feat-export-some-classes-and-make-some-methods.patch @@ -0,0 +1,35 @@ +From d0564b8023c85678a7eb9c6b1e7696259053d20e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:17:05 +0100 +Subject: [PATCH 42/58] fixup! feat: export some classes and make some methods + accessible + +--- + .../workbench/services/extensions/browser/extensionService.ts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts +index 27b6797fd78..098be8e230d 100644 +--- a/src/vs/workbench/services/extensions/browser/extensionService.ts ++++ b/src/vs/workbench/services/extensions/browser/extensionService.ts +@@ -130,7 +130,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten + this._register(this._fileService.registerProvider(Schemas.https, provider)); + } + +- private async _scanWebExtensions(): Promise { ++ protected async _scanWebExtensions(): Promise { + const system: IExtensionDescription[] = [], user: IExtensionDescription[] = [], development: IExtensionDescription[] = []; + try { + await Promise.all([ +@@ -213,7 +213,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten + } + } + +-class BrowserExtensionHostFactory implements IExtensionHostFactory { ++export class BrowserExtensionHostFactory implements IExtensionHostFactory { + + constructor( + private readonly _extensionsProposedApi: ExtensionsProposedApi, +-- +2.34.1 + diff --git a/vscode-paches/0043-refactor-split-class-in-2.patch b/vscode-paches/0043-refactor-split-class-in-2.patch new file mode 100644 index 00000000..d50f9ac4 --- /dev/null +++ b/vscode-paches/0043-refactor-split-class-in-2.patch @@ -0,0 +1,139 @@ +From da03c4c2ff60093a267b457025b3822f7f2cd004 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:17:31 +0100 +Subject: [PATCH 43/58] refactor: split class in 2 + +--- + .../extensions/browser/extensionService.ts | 94 +++++++++++++++---- + 1 file changed, 76 insertions(+), 18 deletions(-) + +diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts +index 098be8e230d..0b12e5972ce 100644 +--- a/src/vs/workbench/services/extensions/browser/extensionService.ts ++++ b/src/vs/workbench/services/extensions/browser/extensionService.ts +@@ -43,8 +43,10 @@ import { IUserDataInitializationService } from 'vs/workbench/services/userData/b + import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; + + export class ExtensionService extends AbstractExtensionService implements IExtensionService { +- + constructor( ++ extensionsProposedApi: ExtensionsProposedApi, ++ extensionHostFactory: IExtensionHostFactory, ++ extensionHostKindPicker: IExtensionHostKindPicker, + @IInstantiationService instantiationService: IInstantiationService, + @INotificationService notificationService: INotificationService, + @IBrowserWorkbenchEnvironmentService private readonly _browserEnvironmentService: IBrowserWorkbenchEnvironmentService, +@@ -68,21 +70,10 @@ export class ExtensionService extends AbstractExtensionService implements IExten + @IRemoteExplorerService private readonly _remoteExplorerService: IRemoteExplorerService, + @IDialogService dialogService: IDialogService, + ) { +- const extensionsProposedApi = instantiationService.createInstance(ExtensionsProposedApi); +- const extensionHostFactory = new BrowserExtensionHostFactory( +- extensionsProposedApi, +- () => this._scanWebExtensions(), +- () => this._getExtensionRegistrySnapshotWhenReady(), +- instantiationService, +- remoteAgentService, +- remoteAuthorityResolverService, +- extensionEnablementService, +- logService +- ); + super( + extensionsProposedApi, + extensionHostFactory, +- new BrowserExtensionHostKindPicker(logService), ++ extensionHostKindPicker, + instantiationService, + notificationService, + _browserEnvironmentService, +@@ -219,10 +210,10 @@ export class BrowserExtensionHostFactory implements IExtensionHostFactory { + private readonly _extensionsProposedApi: ExtensionsProposedApi, + private readonly _scanWebExtensions: () => Promise, + private readonly _getExtensionRegistrySnapshotWhenReady: () => Promise, +- @IInstantiationService private readonly _instantiationService: IInstantiationService, +- @IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService, +- @IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, +- @IWorkbenchExtensionEnablementService private readonly _extensionEnablementService: IWorkbenchExtensionEnablementService, ++ @IInstantiationService protected readonly _instantiationService: IInstantiationService, ++ @IRemoteAgentService protected readonly _remoteAgentService: IRemoteAgentService, ++ @IRemoteAuthorityResolverService protected readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, ++ @IWorkbenchExtensionEnablementService protected readonly _extensionEnablementService: IWorkbenchExtensionEnablementService, + @ILogService private readonly _logService: ILogService, + ) { } + +@@ -346,4 +337,71 @@ export class BrowserExtensionHostKindPicker implements IExtensionHostKindPicker + } + } + +-registerSingleton(IExtensionService, ExtensionService, InstantiationType.Eager); ++export class BrowserExtensionService extends ExtensionService { ++ constructor( ++ @IInstantiationService instantiationService: IInstantiationService, ++ @INotificationService notificationService: INotificationService, ++ @IBrowserWorkbenchEnvironmentService browserEnvironmentService: IBrowserWorkbenchEnvironmentService, ++ @ITelemetryService telemetryService: ITelemetryService, ++ @IWorkbenchExtensionEnablementService extensionEnablementService: IWorkbenchExtensionEnablementService, ++ @IFileService fileService: IFileService, ++ @IProductService productService: IProductService, ++ @IWorkbenchExtensionManagementService extensionManagementService: IWorkbenchExtensionManagementService, ++ @IWorkspaceContextService contextService: IWorkspaceContextService, ++ @IConfigurationService configurationService: IConfigurationService, ++ @IExtensionManifestPropertiesService extensionManifestPropertiesService: IExtensionManifestPropertiesService, ++ @IWebExtensionsScannerService webExtensionsScannerService: IWebExtensionsScannerService, ++ @ILogService logService: ILogService, ++ @IRemoteAgentService remoteAgentService: IRemoteAgentService, ++ @IRemoteExtensionsScannerService remoteExtensionsScannerService: IRemoteExtensionsScannerService, ++ @ILifecycleService lifecycleService: ILifecycleService, ++ @IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService, ++ @IUserDataInitializationService userDataInitializationService: IUserDataInitializationService, ++ @IUserDataProfileService userDataProfileService: IUserDataProfileService, ++ @IWorkspaceTrustManagementService workspaceTrustManagementService: IWorkspaceTrustManagementService, ++ @IRemoteExplorerService remoteExplorerService: IRemoteExplorerService, ++ @IDialogService dialogService: IDialogService, ++ ) { ++ const extensionsProposedApi = instantiationService.createInstance(ExtensionsProposedApi); ++ const extensionHostFactory = new BrowserExtensionHostFactory( ++ extensionsProposedApi, ++ () => this._scanWebExtensions(), ++ () => this._getExtensionRegistrySnapshotWhenReady(), ++ instantiationService, ++ remoteAgentService, ++ remoteAuthorityResolverService, ++ extensionEnablementService, ++ logService ++ ); ++ super( ++ extensionsProposedApi, ++ extensionHostFactory, ++ new BrowserExtensionHostKindPicker(logService), ++ instantiationService, ++ notificationService, ++ browserEnvironmentService, ++ telemetryService, ++ extensionEnablementService, ++ fileService, ++ productService, ++ extensionManagementService, ++ contextService, ++ configurationService, ++ extensionManifestPropertiesService, ++ webExtensionsScannerService, ++ logService, ++ remoteAgentService, ++ remoteExtensionsScannerService, ++ lifecycleService, ++ remoteAuthorityResolverService, ++ userDataInitializationService, ++ userDataProfileService, ++ workspaceTrustManagementService, ++ remoteExplorerService, ++ dialogService ++ ); ++ } ++} ++ ++ ++registerSingleton(IExtensionService, BrowserExtensionService, InstantiationType.Eager); +-- +2.34.1 + diff --git a/vscode-paches/0044-fixup-cleanup-remove-some-checks-and-warnings.patch b/vscode-paches/0044-fixup-cleanup-remove-some-checks-and-warnings.patch new file mode 100644 index 00000000..ab0500d9 --- /dev/null +++ b/vscode-paches/0044-fixup-cleanup-remove-some-checks-and-warnings.patch @@ -0,0 +1,25 @@ +From 2215f84e70f386c76ce6c74d77df42b6f68afccb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:18:03 +0100 +Subject: [PATCH 44/58] fixup! cleanup: remove some checks and warnings + +--- + src/vs/workbench/contrib/webview/browser/pre/service-worker.js | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/vs/workbench/contrib/webview/browser/pre/service-worker.js b/src/vs/workbench/contrib/webview/browser/pre/service-worker.js +index a6e9943b866..c470a1c9ed5 100644 +--- a/src/vs/workbench/contrib/webview/browser/pre/service-worker.js ++++ b/src/vs/workbench/contrib/webview/browser/pre/service-worker.js +@@ -452,7 +452,6 @@ async function getOuterIframeClient(webviewId) { + const allClients = await sw.clients.matchAll({ includeUncontrolled: true }); + return allClients.filter(client => { + const clientUrl = new URL(client.url); +- const hasExpectedPathName = (clientUrl.pathname === `${rootPath}/` || clientUrl.pathname === `${rootPath}/index.html` || clientUrl.pathname === `${rootPath}/index-no-csp.html`); +- return hasExpectedPathName && clientUrl.searchParams.get('id') === webviewId; ++ return clientUrl.searchParams.get('id') === webviewId; + }); + } +-- +2.34.1 + diff --git a/vscode-paches/0045-fix-mark-process-supported-as-soon-as-there-is-a-reg.patch b/vscode-paches/0045-fix-mark-process-supported-as-soon-as-there-is-a-reg.patch new file mode 100644 index 00000000..fbcb7b6e --- /dev/null +++ b/vscode-paches/0045-fix-mark-process-supported-as-soon-as-there-is-a-reg.patch @@ -0,0 +1,43 @@ +From 910b0353811b28fbbce47e2707d70a34cc47f33b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:18:39 +0100 +Subject: [PATCH 45/58] fix: mark process supported as soon as there is a + registered backend + +--- + src/vs/workbench/contrib/terminal/browser/terminalService.ts | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts +index f78008e14db..5cf622e0620 100644 +--- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts ++++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts +@@ -19,7 +19,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c + import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; + import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; + import { INotificationService } from 'vs/platform/notification/common/notification'; +-import { ICreateContributedTerminalProfileOptions, IExtensionTerminalProfile, IPtyHostAttachTarget, IRawTerminalInstanceLayoutInfo, IRawTerminalTabLayoutInfo, IShellLaunchConfig, ITerminalBackend, ITerminalLaunchError, ITerminalLogService, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalExitReason, TerminalLocation, TerminalLocationString, TitleEventSource } from 'vs/platform/terminal/common/terminal'; ++import { ICreateContributedTerminalProfileOptions, IExtensionTerminalProfile, IPtyHostAttachTarget, IRawTerminalInstanceLayoutInfo, IRawTerminalTabLayoutInfo, IShellLaunchConfig, ITerminalBackend, ITerminalBackendRegistry, ITerminalLaunchError, ITerminalLogService, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalExitReason, TerminalExtensions, TerminalLocation, TerminalLocationString, TitleEventSource } from 'vs/platform/terminal/common/terminal'; + import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings'; + import { iconForeground } from 'vs/platform/theme/common/colorRegistry'; + import { getIconRegistry } from 'vs/platform/theme/common/iconRegistry'; +@@ -54,6 +54,7 @@ import { TerminalCapabilityStore } from 'vs/platform/terminal/common/capabilitie + import { ITimerService } from 'vs/workbench/services/timer/browser/timerService'; + import { mark } from 'vs/base/common/performance'; + import { DetachedTerminal } from 'vs/workbench/contrib/terminal/browser/detachedTerminal'; ++import { Registry } from 'vs/platform/registry/common/platform'; + import { ITerminalCapabilityImplMap, TerminalCapability } from 'vs/platform/terminal/common/capabilities/capabilities'; + import { createInstanceCapabilityEventMultiplexer } from 'vs/workbench/contrib/terminal/browser/terminalEvents'; + import { mainWindow } from 'vs/base/browser/window'; +@@ -216,7 +217,7 @@ export class TerminalService extends Disposable implements ITerminalService { + this._handleInstanceContextKeys(); + this._terminalShellTypeContextKey = TerminalContextKeys.shellType.bindTo(this._contextKeyService); + this._processSupportContextKey = TerminalContextKeys.processSupported.bindTo(this._contextKeyService); +- this._processSupportContextKey.set(!isWeb || this._remoteAgentService.getConnection() !== null); ++ this._processSupportContextKey.set(!isWeb || this._remoteAgentService.getConnection() !== null || Registry.as(TerminalExtensions.Backend).getTerminalBackend() !== undefined); + this._terminalHasBeenCreated = TerminalContextKeys.terminalHasBeenCreated.bindTo(this._contextKeyService); + this._terminalCountContextKey = TerminalContextKeys.count.bindTo(this._contextKeyService); + this._terminalEditorActive = TerminalContextKeys.terminalEditorActive.bindTo(this._contextKeyService); +-- +2.34.1 + diff --git a/vscode-paches/0046-fixup-cleanup-remove-some-checks-and-warnings.patch b/vscode-paches/0046-fixup-cleanup-remove-some-checks-and-warnings.patch new file mode 100644 index 00000000..2361b4ec --- /dev/null +++ b/vscode-paches/0046-fixup-cleanup-remove-some-checks-and-warnings.patch @@ -0,0 +1,40 @@ +From fcda1b6d1cec1de033f11141884363727d9dca08 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:19:03 +0100 +Subject: [PATCH 46/58] fixup! cleanup: remove some checks and warnings + +--- + .../contrib/webview/browser/webviewElement.ts | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts +index 6514979da3d..d31d55c9e01 100644 +--- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts ++++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts +@@ -185,11 +185,6 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD + return; + } + +- if (e.origin !== this._webviewContentOrigin(this._encodedWebviewOrigin)) { +- console.log(`Skipped renderer receiving message due to mismatched origins: ${e.origin} ${this._webviewContentOrigin}`); +- return; +- } +- + if (e.data.channel === 'webview-ready') { + if (this._messagePort) { + return; +@@ -536,11 +531,6 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD + return endpoint; + } + +- private _webviewContentOrigin(encodedWebviewOrigin: string): string { +- const uri = URI.parse(this.webviewContentEndpoint(encodedWebviewOrigin)); +- return uri.scheme + '://' + uri.authority.toLowerCase(); +- } +- + private doPostMessage(channel: string, data?: any, transferable: Transferable[] = []): boolean { + if (this.element && this._messagePort) { + this._messagePort.postMessage({ channel, args: data }, transferable); +-- +2.34.1 + diff --git a/vscode-paches/0047-fix-use-asBrowserUri-to-get-iframe-src.patch b/vscode-paches/0047-fix-use-asBrowserUri-to-get-iframe-src.patch new file mode 100644 index 00000000..1a88dbda --- /dev/null +++ b/vscode-paches/0047-fix-use-asBrowserUri-to-get-iframe-src.patch @@ -0,0 +1,26 @@ +From 2f696f65b0e046500d4790b1e1e562703ea4f34e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:21:20 +0100 +Subject: [PATCH 47/58] fix: use asBrowserUri to get iframe src + +--- + src/vs/workbench/contrib/webview/browser/webviewElement.ts | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts +index d31d55c9e01..51405ded346 100644 +--- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts ++++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts +@@ -477,7 +477,8 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD + // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1754872 + const fileName = isFirefox ? 'index-no-csp.html' : 'index.html'; + +- this.element!.setAttribute('src', `${this.webviewContentEndpoint(encodedWebviewOrigin)}/${fileName}?${queryString}`); ++ const relativeIframeSrc = FileAccess.asBrowserUri(`vs/workbench/contrib/webview/browser/pre/${fileName}`); ++ this.element!.setAttribute('src', `${relativeIframeSrc.toString(true)}?${queryString}`); + } + + public mountTo(element: HTMLElement) { +-- +2.34.1 + diff --git a/vscode-paches/0048-feat-add-some-parameter-to-webview-iframes.patch b/vscode-paches/0048-feat-add-some-parameter-to-webview-iframes.patch new file mode 100644 index 00000000..c0a18369 --- /dev/null +++ b/vscode-paches/0048-feat-add-some-parameter-to-webview-iframes.patch @@ -0,0 +1,35 @@ +From 3055ece4edf9d4f94516ef1fe9658f10c1b6af2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:21:40 +0100 +Subject: [PATCH 48/58] feat: add some parameter to webview iframes + +--- + src/vs/workbench/contrib/webview/browser/webviewElement.ts | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts +index 51405ded346..e05a401c479 100644 +--- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts ++++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts +@@ -11,7 +11,7 @@ import { streamToBuffer, VSBufferReadableStream } from 'vs/base/common/buffer'; + import { CancellationTokenSource } from 'vs/base/common/cancellation'; + import { Emitter, Event } from 'vs/base/common/event'; + import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +-import { COI } from 'vs/base/common/network'; ++import { COI, FileAccess } from 'vs/base/common/network'; + import { URI } from 'vs/base/common/uri'; + import { generateUuid } from 'vs/base/common/uuid'; + import { localize } from 'vs/nls'; +@@ -470,6 +470,9 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD + params.purpose = options.purpose; + } + ++ params.serviceWorkerUri = FileAccess.asBrowserUri('vs/workbench/contrib/webview/browser/pre/service-worker.js').toString(true); ++ params.fakeHtmlUri = FileAccess.asBrowserUri('vs/workbench/contrib/webview/browser/pre/fake.html').toString(true); ++ + COI.addSearchParam(params, true, true); + + const queryString = new URLSearchParams(params).toString(); +-- +2.34.1 + diff --git a/vscode-paches/0049-fix-replace-CJS-require-by-FileAccess.toModuleConten.patch b/vscode-paches/0049-fix-replace-CJS-require-by-FileAccess.toModuleConten.patch new file mode 100644 index 00000000..a53728b9 --- /dev/null +++ b/vscode-paches/0049-fix-replace-CJS-require-by-FileAccess.toModuleConten.patch @@ -0,0 +1,92 @@ +From 1b620e23dbdc07012f6e43998edd6cb4bbc7d058 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:22:25 +0100 +Subject: [PATCH 49/58] fix: replace CJS require by FileAccess.toModuleContent + +to make it work in ESM context +--- + .../browser/gettingStartedDetailsRenderer.ts | 12 +++++------- + .../common/walkThroughContentProvider.ts | 18 +++++------------- + 2 files changed, 10 insertions(+), 20 deletions(-) + +diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts +index 869f44526b4..296ac140860 100644 +--- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts ++++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedDetailsRenderer.ts +@@ -17,6 +17,7 @@ import { IFileService } from 'vs/platform/files/common/files'; + import { INotificationService } from 'vs/platform/notification/common/notification'; + import { ILanguageService } from 'vs/editor/common/languages/language'; + import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; ++import { AppResourcePath, FileAccess } from 'vs/base/common/network'; + + + export class GettingStartedDetailsRenderer { +@@ -221,12 +222,9 @@ export class GettingStartedDetailsRenderer { + try { + const moduleId = JSON.parse(path.query).moduleId; + if (useModuleId && moduleId) { +- const contents = await new Promise(c => { +- require([moduleId], content => { +- c(content.default()); +- }); +- }); +- return contents; ++ const content = await FileAccess.toModuleContent<() => Promise>(moduleId); ++ ++ return content(); + } + } catch { } + +@@ -262,7 +260,7 @@ export class GettingStartedDetailsRenderer { + } + + const transformUri = (src: string, base: URI) => { +- const path = joinPath(base, src); ++ const path = FileAccess.asBrowserUri(joinPath(base, src).fsPath.slice(1) as AppResourcePath); + return asWebviewUri(path).toString(true); + }; + +diff --git a/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts b/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts +index 24764f1e31a..e16d9f5afcd 100644 +--- a/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts ++++ b/src/vs/workbench/contrib/welcomeWalkthrough/common/walkThroughContentProvider.ts +@@ -10,13 +10,13 @@ import { ITextModel, DefaultEndOfLine, EndOfLinePreference, ITextBufferFactory } + import { ILanguageService } from 'vs/editor/common/languages/language'; + import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; + import { marked } from 'vs/base/common/marked/marked'; +-import { Schemas } from 'vs/base/common/network'; ++import { FileAccess, Schemas } from 'vs/base/common/network'; + import { Range } from 'vs/editor/common/core/range'; + import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; + import { assertIsDefined } from 'vs/base/common/types'; +-import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; ++import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; + +-export function requireToContent(instantiationService: IInstantiationService, resource: URI): Promise { ++export async function requireToContent(instantiationService: IInstantiationService, resource: URI): Promise { + if (!resource.query) { + throw new Error('Welcome: invalid resource'); + } +@@ -26,17 +26,9 @@ export function requireToContent(instantiationService: IInstantiationService, re + throw new Error('Welcome: invalid resource'); + } + +- const content: Promise = new Promise((resolve, reject) => { +- require([query.moduleId], content => { +- try { +- resolve(instantiationService.invokeFunction(content.default)); +- } catch (err) { +- reject(err); +- } +- }); +- }); ++ const content = await FileAccess.toModuleContent<(accessor: ServicesAccessor) => Promise>(query.moduleId); + +- return content; ++ return instantiationService.invokeFunction(content); + } + + export class WalkThroughSnippetContentProvider implements ITextModelContentProvider, IWorkbenchContribution { +-- +2.34.1 + diff --git a/vscode-paches/0050-fix-only-detect-fullscreen-if-it-s-not-a-guess.patch b/vscode-paches/0050-fix-only-detect-fullscreen-if-it-s-not-a-guess.patch new file mode 100644 index 00000000..a205456a --- /dev/null +++ b/vscode-paches/0050-fix-only-detect-fullscreen-if-it-s-not-a-guess.patch @@ -0,0 +1,37 @@ +From 16153ac220cf09abf17a7ff1662d692fbbeb6e99 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:22:48 +0100 +Subject: [PATCH 50/58] fix: only detect fullscreen if it's not a guess + +--- + .../services/host/browser/browserHostService.ts | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts +index 3ce96bba22a..d2067bf7445 100644 +--- a/src/vs/workbench/services/host/browser/browserHostService.ts ++++ b/src/vs/workbench/services/host/browser/browserHostService.ts +@@ -213,13 +213,18 @@ export class BrowserHostService extends Disposable implements IHostService { + const windowId = getWindowId(window); + const viewport = isIOS && window.visualViewport ? window.visualViewport /** Visual viewport */ : window /** Layout viewport */; + ++ const isFullScreen = () => { ++ const fullScreen = detectFullscreen(window); ++ return fullScreen !== null && !fullScreen.guess; ++ }; ++ + // Fullscreen (Browser) + for (const event of [EventType.FULLSCREEN_CHANGE, EventType.WK_FULLSCREEN_CHANGE]) { +- disposables.add(addDisposableListener(window.document, event, () => emitter.fire({ windowId, fullscreen: !!detectFullscreen(window) }))); ++ disposables.add(addDisposableListener(window.document, event, () => emitter.fire({ windowId, fullscreen: isFullScreen() }))); + } + + // Fullscreen (Native) +- disposables.add(addDisposableThrottledListener(viewport, EventType.RESIZE, () => emitter.fire({ windowId, fullscreen: !!detectFullscreen(window) }), undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */)); ++ disposables.add(addDisposableThrottledListener(viewport, EventType.RESIZE, () => emitter.fire({ windowId, fullscreen: isFullScreen() }), undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */)); + }, { window: mainWindow, disposables: this._store })); + + return emitter.event; +-- +2.34.1 + diff --git a/vscode-paches/0051-fixup-refactor-split-code.patch b/vscode-paches/0051-fixup-refactor-split-code.patch new file mode 100644 index 00000000..195166c7 --- /dev/null +++ b/vscode-paches/0051-fixup-refactor-split-code.patch @@ -0,0 +1,32 @@ +From eb444dfb4a70d1d5464de92faf056b1687e927af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:23:19 +0100 +Subject: [PATCH 51/58] fixup! refactor: split code + +--- + .../services/keybinding/browser/keybindingService.ts | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/vs/workbench/services/keybinding/browser/keybindingService.ts b/src/vs/workbench/services/keybinding/browser/keybindingService.ts +index cbed3a6137c..956db0ac3bd 100644 +--- a/src/vs/workbench/services/keybinding/browser/keybindingService.ts ++++ b/src/vs/workbench/services/keybinding/browser/keybindingService.ts +@@ -428,10 +428,14 @@ export class WorkbenchKeybindingService extends AbstractKeybindingService { + this._onDidUpdateKeybindings.fire(); + } + ++ protected getUserKeybindingItems() { ++ return this._resolveUserKeybindingItems(this.userKeybindings.keybindings, false); ++ } ++ + protected _getResolver(): KeybindingResolver { + if (!this._cachedResolver) { + const defaults = this._resolveKeybindingItems(KeybindingsRegistry.getDefaultKeybindings(), true); +- const overrides = this._resolveUserKeybindingItems(this.userKeybindings.keybindings, false); ++ const overrides = this.getUserKeybindingItems(); + this._cachedResolver = new KeybindingResolver(defaults, overrides, (str) => this._log(str)); + } + return this._cachedResolver; +-- +2.34.1 + diff --git a/vscode-paches/0052-fix-only-try-once-to-access-the-navigator.keyboard-o.patch b/vscode-paches/0052-fix-only-try-once-to-access-the-navigator.keyboard-o.patch new file mode 100644 index 00000000..db9a471e --- /dev/null +++ b/vscode-paches/0052-fix-only-try-once-to-access-the-navigator.keyboard-o.patch @@ -0,0 +1,46 @@ +From fcf6d85c7f4a122078cc8ca9c00cc57ee1a94951 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:23:55 +0100 +Subject: [PATCH 52/58] fix: only try once to access the navigator.keyboard + object + +--- + .../services/keybinding/browser/keyboardLayoutService.ts | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts b/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts +index bb50e96ff77..ab8d76f8903 100644 +--- a/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts ++++ b/src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts +@@ -42,6 +42,7 @@ export class BrowserKeyboardMapperFactoryBase extends Disposable { + protected _keymapInfos: KeymapInfo[]; + protected _mru: KeymapInfo[]; + private _activeKeymapInfo: KeymapInfo | null; ++ private keyboardLayoutMapAllowed: boolean = (navigator as any).keyboard !== undefined; + + get activeKeymap(): KeymapInfo | null { + return this._activeKeymapInfo; +@@ -394,7 +395,7 @@ export class BrowserKeyboardMapperFactoryBase extends Disposable { + } + + private async _getBrowserKeyMapping(keyboardEvent?: IKeyboardEvent): Promise { +- if ((navigator as any).keyboard) { ++ if (this.keyboardLayoutMapAllowed) { + try { + return await (navigator as any).keyboard.getLayoutMap().then((e: any) => { + const ret: IKeyboardMapping = {}; +@@ -419,8 +420,10 @@ export class BrowserKeyboardMapperFactoryBase extends Disposable { + }); + } catch { + // getLayoutMap can throw if invoked from a nested browsing context ++ this.keyboardLayoutMapAllowed = false; + } +- } else if (keyboardEvent && !keyboardEvent.shiftKey && !keyboardEvent.altKey && !keyboardEvent.metaKey && !keyboardEvent.metaKey) { ++ } ++ if (keyboardEvent && !keyboardEvent.shiftKey && !keyboardEvent.altKey && !keyboardEvent.metaKey && !keyboardEvent.metaKey) { + const ret: IKeyboardMapping = {}; + const standardKeyboardEvent = keyboardEvent as StandardKeyboardEvent; + ret[standardKeyboardEvent.browserEvent.code] = { +-- +2.34.1 + diff --git a/vscode-paches/0053-fix-only-use-open-model.patch b/vscode-paches/0053-fix-only-use-open-model.patch new file mode 100644 index 00000000..6131245f --- /dev/null +++ b/vscode-paches/0053-fix-only-use-open-model.patch @@ -0,0 +1,115 @@ +From 2605674d58bdbb152525e4eda26944b41ce15e90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:24:35 +0100 +Subject: [PATCH 53/58] fix: only use open model + +--- + .../browser/languageDetectionSimpleWorker.ts | 61 +------------------ + 1 file changed, 3 insertions(+), 58 deletions(-) + +diff --git a/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts b/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts +index f967fc38127..4da1da8f591 100644 +--- a/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts ++++ b/src/vs/workbench/services/languageDetection/browser/languageDetectionSimpleWorker.ts +@@ -3,14 +3,12 @@ + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +-import type { ModelOperations, ModelResult } from '@vscode/vscode-languagedetection'; ++import { ModelOperations, ModelResult } from '@vscode/vscode-languagedetection'; + import { StopWatch } from 'vs/base/common/stopwatch'; + import { IRequestHandler } from 'vs/base/common/worker/simpleWorker'; + import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker'; + import { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost'; + +-type RegexpModel = { detect: (inp: string, langBiases: Record, supportedLangs?: string[]) => string | undefined }; +- + /** + * Called on the worker side + * @internal +@@ -28,9 +26,6 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker { + private static readonly positiveConfidenceCorrectionBucket2 = 0.025; + private static readonly negativeConfidenceCorrection = 0.5; + +- private _regexpModel: RegexpModel | undefined; +- private _regexpLoadFailed: boolean = false; +- + private _modelOperations: ModelOperations | undefined; + private _loadFailed: boolean = false; + +@@ -63,19 +58,8 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker { + return undefined; + }; + +- const historicalResolver = async () => this.runRegexpModel(documentTextSample, langBiases ?? {}, supportedLangs); +- +- if (preferHistory) { +- const history = await historicalResolver(); +- if (history) { return history; } +- const neural = await neuralResolver(); +- if (neural) { return neural; } +- } else { +- const neural = await neuralResolver(); +- if (neural) { return neural; } +- const history = await historicalResolver(); +- if (history) { return history; } +- } ++ const neural = await neuralResolver(); ++ if (neural) { return neural; } + + return undefined; + } +@@ -94,50 +78,11 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker { + return content; + } + +- private async getRegexpModel(): Promise { +- if (this._regexpLoadFailed) { +- return; +- } +- if (this._regexpModel) { +- return this._regexpModel; +- } +- const uri: string = await this._host.fhr('getRegexpModelUri', []); +- try { +- this._regexpModel = await import(uri) as RegexpModel; +- return this._regexpModel; +- } catch (e) { +- this._regexpLoadFailed = true; +- // console.warn('error loading language detection model', e); +- return; +- } +- } +- +- private async runRegexpModel(content: string, langBiases: Record, supportedLangs?: string[]): Promise { +- const regexpModel = await this.getRegexpModel(); +- if (!regexpModel) { return; } +- +- if (supportedLangs?.length) { +- // When using supportedLangs, normally computed biases are too extreme. Just use a "bitmask" of sorts. +- for (const lang of Object.keys(langBiases)) { +- if (supportedLangs.includes(lang)) { +- langBiases[lang] = 1; +- } else { +- langBiases[lang] = 0; +- } +- } +- } +- +- const detected = regexpModel.detect(content, langBiases, supportedLangs); +- return detected; +- } +- + private async getModelOperations(): Promise { + if (this._modelOperations) { + return this._modelOperations; + } + +- const uri: string = await this._host.fhr('getIndexJsUri', []); +- const { ModelOperations } = await import(uri) as typeof import('@vscode/vscode-languagedetection'); + this._modelOperations = new ModelOperations({ + modelJsonLoaderFunc: async () => { + const response = await fetch(await this._host.fhr('getModelJsonUri', [])); +-- +2.34.1 + diff --git a/vscode-paches/0054-fix-allow-adding-a-local-folder-even-when-there-is-a.patch b/vscode-paches/0054-fix-allow-adding-a-local-folder-even-when-there-is-a.patch new file mode 100644 index 00000000..be71de03 --- /dev/null +++ b/vscode-paches/0054-fix-allow-adding-a-local-folder-even-when-there-is-a.patch @@ -0,0 +1,38 @@ +From 6a0f26e6f7eed4e236145eaf68ed0f5f53898964 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:25:28 +0100 +Subject: [PATCH 54/58] fix: allow adding a local folder even when there is a + remote connection + +--- + .../workspaces/browser/abstractWorkspaceEditingService.ts | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts +index 21312c7e76c..1f89122e0df 100644 +--- a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts ++++ b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts +@@ -14,7 +14,7 @@ import { ConfigurationScope, IConfigurationRegistry, Extensions as Configuration + import { Registry } from 'vs/platform/registry/common/platform'; + import { ICommandService } from 'vs/platform/commands/common/commands'; + import { distinct, firstOrDefault } from 'vs/base/common/arrays'; +-import { basename, isEqual, isEqualAuthority, joinPath, removeTrailingPathSeparator } from 'vs/base/common/resources'; ++import { basename, isEqual, joinPath, removeTrailingPathSeparator } from 'vs/base/common/resources'; + import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; + import { IFileService } from 'vs/platform/files/common/files'; + import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +@@ -169,11 +169,6 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi + + private async doAddFolders(foldersToAdd: IWorkspaceFolderCreationData[], index?: number, donotNotifyError: boolean = false): Promise { + const state = this.contextService.getWorkbenchState(); +- const remoteAuthority = this.environmentService.remoteAuthority; +- if (remoteAuthority) { +- // https://github.com/microsoft/vscode/issues/94191 +- foldersToAdd = foldersToAdd.filter(folder => folder.uri.scheme !== Schemas.file && (folder.uri.scheme !== Schemas.vscodeRemote || isEqualAuthority(folder.uri.authority, remoteAuthority))); +- } + + // If we are in no-workspace or single-folder workspace, adding folders has to + // enter a workspace. +-- +2.34.1 + diff --git a/vscode-paches/0055-feat-allow-to-switch-storage-service-workspace.patch b/vscode-paches/0055-feat-allow-to-switch-storage-service-workspace.patch new file mode 100644 index 00000000..a40804b5 --- /dev/null +++ b/vscode-paches/0055-feat-allow-to-switch-storage-service-workspace.patch @@ -0,0 +1,72 @@ +From 146eeef414318bcbcab150484c5d700754759c83 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:26:01 +0100 +Subject: [PATCH 55/58] feat: allow to switch storage service workspace + +--- + .../storage/browser/storageService.ts | 25 +++++++++++++++---- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/src/vs/workbench/services/storage/browser/storageService.ts b/src/vs/workbench/services/storage/browser/storageService.ts +index a77c2db9446..2b9a8c19926 100644 +--- a/src/vs/workbench/services/storage/browser/storageService.ts ++++ b/src/vs/workbench/services/storage/browser/storageService.ts +@@ -34,6 +34,7 @@ export class BrowserStorageService extends AbstractStorageService { + + private workspaceStorage: IStorage | undefined; + private workspaceStorageDatabase: IIndexedDBStorageDatabase | undefined; ++ private readonly workspaceStorageDisposables = this._register(new DisposableStore()); + + get hasPendingUpdate(): boolean { + return Boolean( +@@ -44,7 +45,7 @@ export class BrowserStorageService extends AbstractStorageService { + } + + constructor( +- private readonly workspace: IAnyWorkspaceIdentifier, ++ private workspace: IAnyWorkspaceIdentifier, + private readonly userDataProfileService: IUserDataProfileService, + @ILogService private readonly logService: ILogService, + ) { +@@ -118,12 +119,15 @@ export class BrowserStorageService extends AbstractStorageService { + } + + private async createWorkspaceStorage(): Promise { ++ // First clear any previously associated disposables ++ this.workspaceStorageDisposables.clear(); ++ + const workspaceStorageIndexedDB = await IndexedDBStorageDatabase.createWorkspaceStorage(this.workspace.id, this.logService); + +- this.workspaceStorageDatabase = this._register(workspaceStorageIndexedDB); +- this.workspaceStorage = this._register(new Storage(this.workspaceStorageDatabase)); ++ this.workspaceStorageDatabase = this.workspaceStorageDisposables.add(workspaceStorageIndexedDB); ++ this.workspaceStorage = this.workspaceStorageDisposables.add(new Storage(this.workspaceStorageDatabase)); + +- this._register(this.workspaceStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.WORKSPACE, e))); ++ this.workspaceStorageDisposables.add(this.workspaceStorage.onDidChangeStorage(e => this.emitDidChangeValue(StorageScope.WORKSPACE, e))); + + await this.workspaceStorage.init(); + +@@ -183,7 +187,18 @@ export class BrowserStorageService extends AbstractStorageService { + } + + protected async switchToWorkspace(toWorkspace: IAnyWorkspaceIdentifier, preserveData: boolean): Promise { +- throw new Error('Migrating storage is currently unsupported in Web'); ++ const oldWorkspaceStorage = assertIsDefined(this.workspaceStorage); ++ const oldItems = preserveData ? oldWorkspaceStorage.items : new Map(); ++ ++ // Close old workpace storage ++ await oldWorkspaceStorage.close(); ++ this.workspace = toWorkspace; ++ ++ // Create new workspace storage & init ++ await this.createWorkspaceStorage(); ++ ++ // Handle data switch and eventing ++ this.switchData(oldItems, assertIsDefined(this.workspaceStorage), StorageScope.WORKSPACE); + } + + protected override shouldFlushWhenIdle(): boolean { +-- +2.34.1 + diff --git a/vscode-paches/0056-cleanup-remove-code-that-we-will-run-ourselves.patch b/vscode-paches/0056-cleanup-remove-code-that-we-will-run-ourselves.patch new file mode 100644 index 00000000..518f8b05 --- /dev/null +++ b/vscode-paches/0056-cleanup-remove-code-that-we-will-run-ourselves.patch @@ -0,0 +1,49 @@ +From 4b5c45bc335946c4760e83edcc49a104e5590c1f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:26:35 +0100 +Subject: [PATCH 56/58] cleanup: remove code that we will run ourselves + +--- + src/vs/workbench/browser/workbench.ts | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts +index 56e9b6f58cf..bea66a053e5 100644 +--- a/src/vs/workbench/browser/workbench.ts ++++ b/src/vs/workbench/browser/workbench.ts +@@ -11,10 +11,7 @@ import { RunOnceScheduler, timeout } from 'vs/base/common/async'; + import { isFirefox, isSafari, isChrome } from 'vs/base/browser/browser'; + import { mark } from 'vs/base/common/performance'; + import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors'; +-import { Registry } from 'vs/platform/registry/common/platform'; + import { isWindows, isLinux, isWeb, isNative, isMacintosh } from 'vs/base/common/platform'; +-import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; +-import { IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; + import { getSingletonServiceDescriptors } from 'vs/platform/instantiation/common/extensions'; + import { Position, Parts, IWorkbenchLayoutService, positionToString } from 'vs/workbench/services/layout/browser/layoutService'; + import { IStorageService, WillSaveStateReason, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +@@ -35,7 +32,6 @@ import { FontMeasurements } from 'vs/editor/browser/config/fontMeasurements'; + import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; + import { ILogService } from 'vs/platform/log/common/log'; + import { toErrorMessage } from 'vs/base/common/errorMessage'; +-import { WorkbenchContextKeysHandler } from 'vs/workbench/browser/contextkeys'; + import { coalesce } from 'vs/base/common/arrays'; + import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; + import { Layout } from 'vs/workbench/browser/layout'; +@@ -161,13 +157,6 @@ export class Workbench extends Layout { + // Layout + this.initLayout(accessor); + +- // Registries +- Registry.as(WorkbenchExtensions.Workbench).start(accessor); +- Registry.as(EditorExtensions.EditorFactory).start(accessor); +- +- // Context Keys +- this._register(instantiationService.createInstance(WorkbenchContextKeysHandler)); +- + // Register Listeners + this.registerListeners(lifecycleService, storageService, configurationService, hostService, dialogService); + +-- +2.34.1 + diff --git a/vscode-paches/0057-fix-typescript-use-import-function-able-to-replace-i.patch b/vscode-paches/0057-fix-typescript-use-import-function-able-to-replace-i.patch new file mode 100644 index 00000000..9984888b --- /dev/null +++ b/vscode-paches/0057-fix-typescript-use-import-function-able-to-replace-i.patch @@ -0,0 +1,26 @@ +From bda500a3251a5eea253d69dbb81f27808744b395 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:27:13 +0100 +Subject: [PATCH 57/58] fix(typescript): use import function able to replace + imported url + +--- + extensions/typescript-language-features/web/src/serverHost.ts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/typescript-language-features/web/src/serverHost.ts b/extensions/typescript-language-features/web/src/serverHost.ts +index f2f9ca95996..f5c28ec0cab 100644 +--- a/extensions/typescript-language-features/web/src/serverHost.ts ++++ b/extensions/typescript-language-features/web/src/serverHost.ts +@@ -88,7 +88,7 @@ function createServerHost( + + const scriptPath = combinePaths(packageRoot, browser); + try { +- const { default: module } = await import(/* webpackIgnore: true */ scriptPath); ++ const { default: module } = await new Function('url', 'return importExt(url)')(scriptPath); + return { module, error: undefined }; + } catch (e) { + return { module: undefined, error: e }; +-- +2.34.1 + diff --git a/vscode-paches/0058-cleanup-remove-graceful-fs.patch b/vscode-paches/0058-cleanup-remove-graceful-fs.patch new file mode 100644 index 00000000..abddac9b --- /dev/null +++ b/vscode-paches/0058-cleanup-remove-graceful-fs.patch @@ -0,0 +1,47 @@ +From 27246fe31bf918770171eca8dc456335c4cd4d31 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lo=C3=AFc=20Mangeonjean?= +Date: Mon, 11 Mar 2024 18:27:43 +0100 +Subject: [PATCH 58/58] cleanup: remove graceful-fs + +--- + .../platform/files/node/diskFileSystemProvider.ts | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/src/vs/platform/files/node/diskFileSystemProvider.ts b/src/vs/platform/files/node/diskFileSystemProvider.ts +index 180aa7e2960..d589be25ed6 100644 +--- a/src/vs/platform/files/node/diskFileSystemProvider.ts ++++ b/src/vs/platform/files/node/diskFileSystemProvider.ts +@@ -4,7 +4,6 @@ + *--------------------------------------------------------------------------------------------*/ + + import * as fs from 'fs'; +-import { gracefulify } from 'graceful-fs'; + import { Barrier, retry } from 'vs/base/common/async'; + import { ResourceMap } from 'vs/base/common/map'; + import { VSBuffer } from 'vs/base/common/buffer'; +@@ -24,22 +23,9 @@ import { readFileIntoStream } from 'vs/platform/files/common/io'; + import { AbstractNonRecursiveWatcherClient, AbstractUniversalWatcherClient, ILogMessage } from 'vs/platform/files/common/watcher'; + import { ILogService } from 'vs/platform/log/common/log'; + import { AbstractDiskFileSystemProvider, IDiskFileSystemProviderOptions } from 'vs/platform/files/common/diskFileSystemProvider'; +-import { toErrorMessage } from 'vs/base/common/errorMessage'; + import { UniversalWatcherClient } from 'vs/platform/files/node/watcher/watcherClient'; + import { NodeJSWatcherClient } from 'vs/platform/files/node/watcher/nodejs/nodejsClient'; + +-/** +- * Enable graceful-fs very early from here to have it enabled +- * in all contexts that leverage the disk file system provider. +- */ +-(() => { +- try { +- gracefulify(fs); +- } catch (error) { +- console.error(`Error enabling graceful-fs: ${toErrorMessage(error)}`); +- } +-})(); +- + export class DiskFileSystemProvider extends AbstractDiskFileSystemProvider implements + IFileSystemProviderWithFileReadWriteCapability, + IFileSystemProviderWithOpenReadWriteCloseCapability, +-- +2.34.1 +