diff --git a/.eslintrc.json b/.eslintrc.json index b41c9414957..65054e9b4a4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -63,13 +63,18 @@ "browser": [ "common" ], - "electron-main": [ + "electron-sandbox": [ "common", - "node" + "browser" ], "electron-browser": [ "common", "browser", + "node", + "electron-sandbox" + ], + "electron-main": [ + "common", "node" ] } @@ -104,6 +109,14 @@ "**/vs/base/{common,browser}/**" ] }, + { + "target": "**/vs/base/electron-sandbox/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/{common,browser,electron-sandbox}/**" + ] + }, { "target": "**/vs/base/node/**", "restrictions": [ @@ -149,13 +162,22 @@ "*" // node modules ] }, + { + "target": "**/vs/base/parts/*/electron-sandbox/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/{common,browser,electron-sandbox}/**", + "**/vs/base/parts/*/{common,browser,electron-sandbox}/**" + ] + }, { "target": "**/vs/base/parts/*/electron-browser/**", "restrictions": [ "vs/nls", "vs/css!./**/*", - "**/vs/base/{common,browser,node,electron-browser}/**", - "**/vs/base/parts/*/{common,browser,node,electron-browser}/**", + "**/vs/base/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/base/parts/*/{common,browser,node,electron-sandbox,electron-browser}/**", "*" // node modules ] }, @@ -210,14 +232,24 @@ "*" // node modules ] }, + { + "target": "**/vs/platform/*/electron-sandbox/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/{common,browser,electron-sandbox}/**", + "**/vs/base/parts/*/{common,browser,electron-sandbox}/**", + "**/vs/platform/*/{common,browser,electron-sandbox}/**" + ] + }, { "target": "**/vs/platform/*/electron-browser/**", "restrictions": [ "vs/nls", "vs/css!./**/*", - "**/vs/base/{common,browser,node}/**", - "**/vs/base/parts/*/{common,browser,node,electron-browser}/**", - "**/vs/platform/*/{common,browser,node,electron-browser}/**", + "**/vs/base/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/base/parts/*/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/platform/*/{common,browser,node,electron-sandbox,electron-browser}/**", "*" // node modules ] }, @@ -421,18 +453,34 @@ "**/vs/**/{common,worker}/**" ] }, + { + "target": "**/vs/workbench/electron-sandbox/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/{common,browser,electron-sandbox}/**", + "**/vs/base/parts/*/{common,browser,electron-sandbox}/**", + "**/vs/platform/*/{common,browser,electron-sandbox}/**", + "**/vs/editor/{common,browser,electron-sandbox}/**", + "**/vs/editor/contrib/**", // editor/contrib is equivalent to /browser/ by convention + "**/vs/workbench/{common,browser,electron-sandbox}/**", + "**/vs/workbench/api/{common,browser,electron-sandbox}/**", + "**/vs/workbench/services/*/{common,browser,electron-sandbox}/**" + ] + }, { "target": "**/vs/workbench/electron-browser/**", "restrictions": [ "vs/nls", "vs/css!./**/*", - "**/vs/base/{common,browser,node,electron-browser}/**", - "**/vs/base/parts/*/{common,browser,node,electron-browser}/**", - "**/vs/platform/*/{common,browser,node,electron-browser}/**", - "**/vs/editor/{common,browser,node,electron-browser}/**", + "**/vs/base/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/base/parts/*/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/platform/*/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/editor/{common,browser,node,electron-sandbox,electron-browser}/**", "**/vs/editor/contrib/**", // editor/contrib is equivalent to /browser/ by convention - "**/vs/workbench/{common,browser,node,electron-browser,api}/**", - "**/vs/workbench/services/*/{common,browser,node,electron-browser}/**", + "**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/api/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/services/*/{common,browser,node,electron-sandbox,electron-browser}/**", "*" // node modules ] }, @@ -444,7 +492,7 @@ "**/vs/base/**", "**/vs/platform/**", "**/vs/editor/**", - "**/vs/workbench/{common,browser,node,electron-browser}/**", + "**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**", "vs/workbench/contrib/files/common/editors/fileEditorInput", "**/vs/workbench/services/**", "**/vs/workbench/test/**", @@ -508,16 +556,30 @@ "*" // node modules ] }, + { + "target": "**/vs/workbench/services/**/electron-sandbox/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/**/{common,browser,worker,electron-sandbox}/**", + "**/vs/platform/**/{common,browser,electron-sandbox}/**", + "**/vs/editor/**", + "**/vs/workbench/{common,browser,electron-sandbox}/**", + "**/vs/workbench/api/{common,browser,electron-sandbox}/**", + "**/vs/workbench/services/**/{common,browser,electron-sandbox}/**" + ] + }, { "target": "**/vs/workbench/services/**/electron-browser/**", "restrictions": [ "vs/nls", "vs/css!./**/*", - "**/vs/base/**/{common,browser,worker,node,electron-browser}/**", - "**/vs/platform/**/{common,browser,node,electron-browser}/**", + "**/vs/base/**/{common,browser,worker,node,electron-sandbox,electron-browser}/**", + "**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**", "**/vs/editor/**", - "**/vs/workbench/{common,browser,node,electron-browser,api}/**", - "**/vs/workbench/services/**/{common,browser,node,electron-browser}/**", + "**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/api/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/services/**/{common,browser,node,electron-sandbox,electron-browser}/**", "*" // node modules ] }, @@ -530,7 +592,7 @@ "**/vs/base/**", "**/vs/platform/**", "**/vs/editor/**", - "**/vs/workbench/{common,browser,node,electron-browser}/**", + "**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**", "**/vs/workbench/services/**", "**/vs/workbench/contrib/**", "**/vs/workbench/test/**", @@ -624,17 +686,32 @@ "*" // node modules ] }, + { + "target": "**/vs/workbench/contrib/**/electron-sandbox/**", + "restrictions": [ + "vs/nls", + "vs/css!./**/*", + "**/vs/base/**/{common,browser,worker,electron-sandbox}/**", + "**/vs/platform/**/{common,browser,electron-sandbox}/**", + "**/vs/editor/**", + "**/vs/workbench/{common,browser,electron-sandbox}/**", + "**/vs/workbench/api/{common,browser,electron-sandbox}/**", + "**/vs/workbench/services/**/{common,browser,electron-sandbox}/**", + "**/vs/workbench/contrib/**/{common,browser,electron-sandbox}/**" + ] + }, { "target": "**/vs/workbench/contrib/**/electron-browser/**", "restrictions": [ "vs/nls", "vs/css!./**/*", - "**/vs/base/**/{common,browser,worker,node,electron-browser}/**", - "**/vs/platform/**/{common,browser,node,electron-browser}/**", + "**/vs/base/**/{common,browser,worker,node,electron-sandbox,electron-browser}/**", + "**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**", "**/vs/editor/**", - "**/vs/workbench/{common,browser,node,electron-browser,api}/**", - "**/vs/workbench/services/**/{common,browser,node,electron-browser}/**", - "**/vs/workbench/contrib/**/{common,browser,node,electron-browser}/**", + "**/vs/workbench/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/api/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/services/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/contrib/**/{common,browser,node,electron-sandbox,electron-browser}/**", "*" // node modules ] }, @@ -654,10 +731,10 @@ "restrictions": [ "vs/nls", "vs/css!./**/*", - "**/vs/base/**/{common,browser,node,electron-browser}/**", - "**/vs/base/parts/**/{common,browser,node,electron-browser}/**", - "**/vs/platform/**/{common,browser,node,electron-browser}/**", - "**/vs/code/**/{common,browser,node,electron-browser}/**", + "**/vs/base/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/base/parts/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/code/**/{common,browser,node,electron-sandbox,electron-browser}/**", "*" // node modules ] }, @@ -685,6 +762,54 @@ "*" // node modules ] }, + { + "target": "**/src/vs/workbench/workbench.common.main.ts", + "restrictions": [ + "vs/nls", + "**/vs/base/**/{common,browser}/**", + "**/vs/base/parts/**/{common,browser}/**", + "**/vs/platform/**/{common,browser}/**", + "**/vs/editor/**", + "**/vs/workbench/**/{common,browser}/**" + ] + }, + { + "target": "**/src/vs/workbench/workbench.web.main.ts", + "restrictions": [ + "vs/nls", + "**/vs/base/**/{common,browser}/**", + "**/vs/base/parts/**/{common,browser}/**", + "**/vs/platform/**/{common,browser}/**", + "**/vs/editor/**", + "**/vs/workbench/**/{common,browser}/**", + "**/vs/workbench/workbench.common.main" + ] + }, + { + "target": "**/src/vs/workbench/workbench.sandbox.main.ts", + "restrictions": [ + "vs/nls", + "**/vs/base/**/{common,browser,electron-sandbox}/**", + "**/vs/base/parts/**/{common,browser,electron-sandbox}/**", + "**/vs/platform/**/{common,browser,electron-sandbox}/**", + "**/vs/editor/**", + "**/vs/workbench/**/{common,browser,electron-sandbox}/**", + "**/vs/workbench/workbench.common.main" + ] + }, + { + "target": "**/src/vs/workbench/workbench.desktop.main.ts", + "restrictions": [ + "vs/nls", + "**/vs/base/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/base/parts/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/platform/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/editor/**", + "**/vs/workbench/**/{common,browser,node,electron-sandbox,electron-browser}/**", + "**/vs/workbench/workbench.common.main", + "**/vs/workbench/workbench.sandbox.main" + ] + }, { "target": "**/extensions/**", "restrictions": "**/*" diff --git a/.github/workflows/author-verified.yml b/.github/workflows/author-verified.yml index e78602ddd11..c4293b05d9d 100644 --- a/.github/workflows/author-verified.yml +++ b/.github/workflows/author-verified.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v2 with: repository: 'microsoft/vscode-github-triage-actions' - ref: v16 + ref: v17 path: ./actions - name: Install Actions if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'author-verification-requested') diff --git a/.github/workflows/classifier-apply.yml b/.github/workflows/classifier-apply.yml index 38e0aabad7f..ff40df8247b 100644 --- a/.github/workflows/classifier-apply.yml +++ b/.github/workflows/classifier-apply.yml @@ -11,7 +11,7 @@ jobs: uses: actions/checkout@v2 with: repository: 'microsoft/vscode-github-triage-actions' - ref: v16 + ref: v17 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml index 127af00a002..6e216904893 100644 --- a/.github/workflows/commands.yml +++ b/.github/workflows/commands.yml @@ -13,7 +13,7 @@ jobs: with: repository: 'microsoft/vscode-github-triage-actions' path: ./actions - ref: v16 + ref: v17 - name: Install Actions run: npm install --production --prefix ./actions - name: Run Commands diff --git a/.github/workflows/english-please.yml b/.github/workflows/english-please.yml index 241fe7b413d..7b7b373be4e 100644 --- a/.github/workflows/english-please.yml +++ b/.github/workflows/english-please.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v2 with: repository: 'microsoft/vscode-github-triage-actions' - ref: v16 + ref: v17 path: ./actions - name: Install Actions if: contains(github.event.issue.labels.*.name, '*english-please') diff --git a/.github/workflows/feature-request.yml b/.github/workflows/feature-request.yml index 3beed1f0e28..e97a6525a3c 100644 --- a/.github/workflows/feature-request.yml +++ b/.github/workflows/feature-request.yml @@ -17,7 +17,7 @@ jobs: with: repository: 'microsoft/vscode-github-triage-actions' path: ./actions - ref: v16 + ref: v17 - name: Install Actions if: github.event_name != 'issues' || contains(github.event.issue.labels.*.name, 'feature-request') run: npm install --production --prefix ./actions diff --git a/.github/workflows/locker.yml b/.github/workflows/locker.yml index e870f6bcb17..2b6f86882c0 100644 --- a/.github/workflows/locker.yml +++ b/.github/workflows/locker.yml @@ -13,7 +13,7 @@ jobs: with: repository: 'microsoft/vscode-github-triage-actions' path: ./actions - ref: v16 + ref: v17 - name: Install Actions run: npm install --production --prefix ./actions - name: Run Locker diff --git a/.github/workflows/needs-more-info-closer.yml b/.github/workflows/needs-more-info-closer.yml index d82efcf97de..630038cd865 100644 --- a/.github/workflows/needs-more-info-closer.yml +++ b/.github/workflows/needs-more-info-closer.yml @@ -13,7 +13,7 @@ jobs: with: repository: 'microsoft/vscode-github-triage-actions' path: ./actions - ref: v16 + ref: v17 - name: Install Actions run: npm install --production --prefix ./actions - name: Run Needs More Info Closer diff --git a/.github/workflows/on-label.yml b/.github/workflows/on-label.yml index 57fe3b3b988..9febd795f33 100644 --- a/.github/workflows/on-label.yml +++ b/.github/workflows/on-label.yml @@ -11,7 +11,7 @@ jobs: uses: actions/checkout@v2 with: repository: 'microsoft/vscode-github-triage-actions' - ref: v16 + ref: v17 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/on-open.yml b/.github/workflows/on-open.yml index a8f501c4656..233a334b471 100644 --- a/.github/workflows/on-open.yml +++ b/.github/workflows/on-open.yml @@ -11,7 +11,7 @@ jobs: uses: actions/checkout@v2 with: repository: 'microsoft/vscode-github-triage-actions' - ref: v16 + ref: v17 path: ./actions - name: Install Actions run: npm install --production --prefix ./actions diff --git a/.github/workflows/test-plan-item-validator.yml b/.github/workflows/test-plan-item-validator.yml index be7d119fa3b..67b8519b2af 100644 --- a/.github/workflows/test-plan-item-validator.yml +++ b/.github/workflows/test-plan-item-validator.yml @@ -14,7 +14,7 @@ jobs: with: repository: 'microsoft/vscode-github-triage-actions' path: ./actions - ref: v16 + ref: v17 - name: Install Actions if: contains(github.event.issue.labels.*.name, 'testplan-item') || contains(github.event.issue.labels.*.name, 'invalid-testplan-item') run: npm install --production --prefix ./actions diff --git a/.yarnrc b/.yarnrc index 59837fea3fc..d86b284e83e 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "8.3.0" +target "7.2.4" runtime "electron" diff --git a/build/builtin/main.js b/build/builtin/main.js index 93cef8cbdad..b094a67cac5 100644 --- a/build/builtin/main.js +++ b/build/builtin/main.js @@ -10,11 +10,11 @@ const path = require('path'); let window = null; app.once('ready', () => { - window = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, webviewTag: true, enableWebSQL: false } }); + window = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, webviewTag: true } }); window.setMenuBarVisibility(false); window.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true })); // window.webContents.openDevTools(); window.once('closed', () => window = null); }); -app.on('window-all-closed', () => app.quit()); +app.on('window-all-closed', () => app.quit()); \ No newline at end of file diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 25b41bd3a91..5881bc66e91 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -66,6 +66,7 @@ const vscodeResources = [ 'out-build/vs/base/node/languagePacks.js', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', 'out-build/vs/base/browser/ui/codicons/codicon/**', + 'out-build/vs/base/parts/sandbox/electron-browser/preload.js', 'out-build/vs/workbench/browser/media/*-theme.css', 'out-build/vs/workbench/contrib/debug/**/*.json', 'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt', @@ -154,6 +155,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op const out = sourceFolderName; const checksums = computeChecksums(out, [ + 'vs/base/parts/sandbox/electron-browser/preload.js', 'vs/workbench/workbench.desktop.main.js', 'vs/workbench/workbench.desktop.main.css', 'vs/workbench/services/extensions/node/extensionHostProcess.js', diff --git a/build/lib/electron.js b/build/lib/electron.js index c459adb6075..bb71f14c12d 100644 --- a/build/lib/electron.js +++ b/build/lib/electron.js @@ -64,7 +64,7 @@ exports.config = { darwinBundleDocumentType(["vue"], 'resources/darwin/vue.icns'), darwinBundleDocumentType(["ascx", "csproj", "dtd", "wxi", "wxl", "wxs", "xml", "xaml"], 'resources/darwin/xml.icns'), darwinBundleDocumentType(["eyaml", "eyml", "yaml", "yml"], 'resources/darwin/yaml.icns'), - darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "lua", "m", "makefile", "ml", "mli", "pl", "pl6", "pm", "pm6", "pod", "pp", "properties", "psgi", "pug", "r", "rs", "rt", "svg", "svgz", "t", "txt", "vb", "xcodeproj", "xcworkspace"], 'resources/darwin/default.icns') + darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "containerfile", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "lua", "m", "makefile", "ml", "mli", "pl", "pl6", "pm", "pm6", "pod", "pp", "properties", "psgi", "pug", "r", "rs", "rt", "svg", "svgz", "t", "txt", "vb", "xcodeproj", "xcworkspace"], 'resources/darwin/default.icns') ], darwinBundleURLTypes: [{ role: 'Viewer', diff --git a/build/lib/electron.ts b/build/lib/electron.ts index 82e9cc5f358..e0beca78079 100644 --- a/build/lib/electron.ts +++ b/build/lib/electron.ts @@ -69,7 +69,7 @@ export const config = { darwinBundleDocumentType(["vue"], 'resources/darwin/vue.icns'), darwinBundleDocumentType(["ascx", "csproj", "dtd", "wxi", "wxl", "wxs", "xml", "xaml"], 'resources/darwin/xml.icns'), darwinBundleDocumentType(["eyaml", "eyml", "yaml", "yml"], 'resources/darwin/yaml.icns'), - darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "lua", "m", "makefile", "ml", "mli", "pl", "pl6", "pm", "pm6", "pod", "pp", "properties", "psgi", "pug", "r", "rs", "rt", "svg", "svgz", "t", "txt", "vb", "xcodeproj", "xcworkspace"], 'resources/darwin/default.icns') + darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "containerfile", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "lua", "m", "makefile", "ml", "mli", "pl", "pl6", "pm", "pm6", "pod", "pp", "properties", "psgi", "pug", "r", "rs", "rt", "svg", "svgz", "t", "txt", "vb", "xcodeproj", "xcworkspace"], 'resources/darwin/default.icns') ], darwinBundleURLTypes: [{ role: 'Viewer', diff --git a/build/lib/layersChecker.js b/build/lib/layersChecker.js index 663769dacea..f3cc2252b5e 100644 --- a/build/lib/layersChecker.js +++ b/build/lib/layersChecker.js @@ -130,6 +130,14 @@ const RULES = [ 'lib.dom.d.ts' // no DOM ] }, + // Electron (sandbox) + { + target: '**/vs/**/electron-sandbox/**', + allowedTypes: CORE_TYPES, + disallowedDefinitions: [ + '@types/node' // no node.js + ] + }, // Electron (renderer): skip { target: '**/vs/**/electron-browser/**', diff --git a/build/lib/layersChecker.ts b/build/lib/layersChecker.ts index 0dcedb8d4e3..508d2b986e9 100644 --- a/build/lib/layersChecker.ts +++ b/build/lib/layersChecker.ts @@ -143,6 +143,15 @@ const RULES = [ ] }, + // Electron (sandbox) + { + target: '**/vs/**/electron-sandbox/**', + allowedTypes: CORE_TYPES, + disallowedDefinitions: [ + '@types/node' // no node.js + ] + }, + // Electron (renderer): skip { target: '**/vs/**/electron-browser/**', diff --git a/build/win32/code.iss b/build/win32/code.iss index 58d2be07883..49b2f255ce3 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -238,6 +238,13 @@ Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.confi Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.config\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\config.ico"; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.config\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.containerfile\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.containerfile\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.containerfile"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.containerfile"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,Containerfile}"; Flags: uninsdeletekey; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.containerfile"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#AppUserId}"; Flags: uninsdeletekey; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.containerfile\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\default.ico"; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.containerfile\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles + Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.cpp\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.cpp\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.cpp"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.cpp"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,C++}"; Flags: uninsdeletekey; Tasks: associatewithfiles diff --git a/cgmanifest.json b/cgmanifest.json index 78f421ca7e0..09478ca403e 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "052d3b44972e6d94ef40054d46c150b7cdd7a5d8" + "commitHash": "e4745133a1d3745f066e068b8033c6a269b59caf" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "80.0.3987.165" + "version": "78.0.3904.130" }, { "component": { @@ -48,11 +48,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "42cce5a9d0fd905bf4ad7a2528c36572dfb8b5ad" + "commitHash": "787378879acfb212ed4ff824bf9f767a24a5cb43a" } }, "isOnlyProductionDependency": true, - "version": "12.13.0" + "version": "12.8.1" }, { "component": { @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "426d45cd8569fb7731f213159336cea019829ec5" + "commitHash": "0552e0d5de46ffa3b481d741f1db5c779e201565" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "8.3.0" + "version": "7.2.4" }, { "component": { diff --git a/extensions/bat/test/colorize-results/test_bat.json b/extensions/bat/test/colorize-results/test_bat.json index 97155fafc8b..eb76b0e1d04 100644 --- a/extensions/bat/test/colorize-results/test_bat.json +++ b/extensions/bat/test/colorize-results/test_bat.json @@ -488,7 +488,7 @@ "t": "source.batchfile constant.character.escape.batchfile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" @@ -510,7 +510,7 @@ "t": "source.batchfile constant.character.escape.batchfile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" diff --git a/extensions/coffeescript/test/colorize-results/test_coffee.json b/extensions/coffeescript/test/colorize-results/test_coffee.json index 7c72176431d..9647307f073 100644 --- a/extensions/coffeescript/test/colorize-results/test_coffee.json +++ b/extensions/coffeescript/test/colorize-results/test_coffee.json @@ -1555,7 +1555,7 @@ "t": "source.coffee string.regexp.multiline.coffee keyword.control.anchor.regexp", "r": { "dark_plus": "keyword.control.anchor.regexp: #DCDCAA", - "light_plus": "keyword.control.anchor.regexp: #FF0000", + "light_plus": "keyword.control.anchor.regexp: #EE0000", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0" @@ -1605,4 +1605,4 @@ "hc_black": "string.regexp: #D16969" } } -] +] \ No newline at end of file diff --git a/extensions/cpp/test/colorize-results/test-78769_cpp.json b/extensions/cpp/test/colorize-results/test-78769_cpp.json index eb114a4f007..82846880603 100644 --- a/extensions/cpp/test/colorize-results/test-78769_cpp.json +++ b/extensions/cpp/test/colorize-results/test-78769_cpp.json @@ -191,7 +191,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -257,7 +257,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -389,7 +389,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.block.struct.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -433,7 +433,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.block.struct.cpp meta.body.struct.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -532,7 +532,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.block.struct.cpp meta.body.struct.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -587,7 +587,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -719,7 +719,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -763,7 +763,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -862,7 +862,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp meta.function.definition.cpp meta.body.function.definition.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -906,7 +906,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -1027,7 +1027,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp meta.block.namespace.cpp meta.body.namespace.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -1071,7 +1071,7 @@ "t": "source.cpp meta.preprocessor.macro.cpp constant.character.escape.line-continuation.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "meta.preprocessor: #569CD6", "light_vs": "meta.preprocessor: #0000FF", "hc_black": "constant.character: #569CD6" @@ -1187,4 +1187,4 @@ "hc_black": "meta.preprocessor: #569CD6" } } -] +] \ No newline at end of file diff --git a/extensions/cpp/test/colorize-results/test_cpp.json b/extensions/cpp/test/colorize-results/test_cpp.json index 108895f8f65..10f6041bb00 100644 --- a/extensions/cpp/test/colorize-results/test_cpp.json +++ b/extensions/cpp/test/colorize-results/test_cpp.json @@ -2314,7 +2314,7 @@ "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp string.quoted.double.cpp constant.character.escape.cpp", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -2430,4 +2430,4 @@ "hc_black": "default: #FFFFFF" } } -] +] \ No newline at end of file diff --git a/extensions/docker/package.json b/extensions/docker/package.json index aa4ef1c294b..c1b91dc283d 100644 --- a/extensions/docker/package.json +++ b/extensions/docker/package.json @@ -12,9 +12,9 @@ "contributes": { "languages": [{ "id": "dockerfile", - "extensions": [ ".dockerfile" ], - "filenames": [ "Dockerfile" ], - "aliases": [ "Dockerfile" ], + "extensions": [ ".dockerfile", ".containerfile" ], + "filenames": [ "Dockerfile", "Containerfile" ], + "aliases": [ "Dockerfile", "Containerfile" ], "configuration": "./language-configuration.json" }], "grammars": [{ diff --git a/extensions/git/package.json b/extensions/git/package.json index 1a5dea75d9f..d33bafbad5f 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -105,6 +105,12 @@ "category": "Git", "icon": "$(add)" }, + { + "command": "git.stageAllMerge", + "title": "%command.stageAllMerge%", + "category": "Git", + "icon": "$(add)" + }, { "command": "git.stageSelectedRanges", "title": "%command.stageSelectedRanges%", @@ -490,6 +496,10 @@ "command": "git.stageAllUntracked", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0" }, + { + "command": "git.stageAllMerge", + "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0" + }, { "command": "git.stageSelectedRanges", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0" @@ -897,12 +907,12 @@ ], "scm/resourceGroup/context": [ { - "command": "git.stageAll", + "command": "git.stageAllMerge", "when": "scmProvider == git && scmResourceGroup == merge", "group": "1_modification" }, { - "command": "git.stageAll", + "command": "git.stageAllMerge", "when": "scmProvider == git && scmResourceGroup == merge", "group": "inline" }, diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 43b13827aa8..be817e22df1 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -14,6 +14,7 @@ "command.stageAll": "Stage All Changes", "command.stageAllTracked": "Stage All Tracked Changes", "command.stageAllUntracked": "Stage All Untracked Changes", + "command.stageAllMerge": "Stage All Merge Changes", "command.stageSelectedRanges": "Stage Selected Ranges", "command.revertSelectedRanges": "Revert Selected Ranges", "command.stageChange": "Stage Change", diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 6beae6fe6f8..e60dc39e6a6 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1000,37 +1000,14 @@ export class CommandCenter { @command('git.stageAll', { repository: true }) async stageAll(repository: Repository): Promise { - const resources = repository.mergeGroup.resourceStates.filter(s => s instanceof Resource) as Resource[]; - const { merge, unresolved, deletionConflicts } = await categorizeResourceByResolution(resources); + const resources = [...repository.workingTreeGroup.resourceStates, ...repository.untrackedGroup.resourceStates]; + const uris = resources.map(r => r.resourceUri); - try { - for (const deletionConflict of deletionConflicts) { - await this._stageDeletionConflict(repository, deletionConflict.resourceUri); - } - } catch (err) { - if (/Cancelled/.test(err.message)) { - return; - } - - throw err; + if (uris.length > 0) { + const config = workspace.getConfiguration('git', Uri.file(repository.root)); + const untrackedChanges = config.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges'); + await repository.add(uris, untrackedChanges === 'mixed' ? undefined : { update: true }); } - - if (unresolved.length > 0) { - const message = unresolved.length > 1 - ? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", merge.length) - : localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(merge[0].resourceUri.fsPath)); - - const yes = localize('yes', "Yes"); - const pick = await window.showWarningMessage(message, { modal: true }, yes); - - if (pick !== yes) { - return; - } - } - - const config = workspace.getConfiguration('git', Uri.file(repository.root)); - const untrackedChanges = config.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges'); - await repository.add([], untrackedChanges === 'mixed' ? undefined : { update: true }); } private async _stageDeletionConflict(repository: Repository, uri: Uri): Promise { @@ -1086,6 +1063,43 @@ export class CommandCenter { await repository.add(uris); } + @command('git.stageAllMerge', { repository: true }) + async stageAllMerge(repository: Repository): Promise { + const resources = repository.mergeGroup.resourceStates.filter(s => s instanceof Resource) as Resource[]; + const { merge, unresolved, deletionConflicts } = await categorizeResourceByResolution(resources); + + try { + for (const deletionConflict of deletionConflicts) { + await this._stageDeletionConflict(repository, deletionConflict.resourceUri); + } + } catch (err) { + if (/Cancelled/.test(err.message)) { + return; + } + + throw err; + } + + if (unresolved.length > 0) { + const message = unresolved.length > 1 + ? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", merge.length) + : localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(merge[0].resourceUri.fsPath)); + + const yes = localize('yes', "Yes"); + const pick = await window.showWarningMessage(message, { modal: true }, yes); + + if (pick !== yes) { + return; + } + } + + const uris = resources.map(r => r.resourceUri); + + if (uris.length > 0) { + await repository.add(uris); + } + } + @command('git.stageChange') async stageChange(uri: Uri, changes: LineChange[], index: number): Promise { const textEditor = window.visibleTextEditors.filter(e => e.document.uri.toString() === uri.toString())[0]; diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index e952280f472..66d91da4d7a 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -1223,15 +1223,13 @@ export class Repository { args.push('-A'); } - args.push('--'); - if (paths && paths.length) { - args.push.apply(args, paths.map(sanitizePath)); + for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) { + await this.run([...args, '--', ...chunk]); + } } else { - args.push('.'); + await this.run([...args, '--', '.']); } - - await this.run(args); } async rm(paths: string[]): Promise { @@ -1440,10 +1438,11 @@ export class Repository { const limiter = new Limiter(5); const promises: Promise[] = []; + const args = ['clean', '-f', '-q']; for (const paths of groups) { for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) { - promises.push(limiter.queue(() => this.run(['clean', '-f', '-q', '--', ...chunk]))); + promises.push(limiter.queue(() => this.run([...args, '--', ...chunk]))); } } @@ -1475,19 +1474,19 @@ export class Repository { // In case there are no branches, we must use rm --cached if (!result.stdout) { - args = ['rm', '--cached', '-r', '--']; + args = ['rm', '--cached', '-r']; } else { - args = ['reset', '-q', treeish, '--']; - } - - if (paths && paths.length) { - args.push.apply(args, paths.map(sanitizePath)); - } else { - args.push('.'); + args = ['reset', '-q', treeish]; } try { - await this.run(args); + if (paths && paths.length > 0) { + for (const chunk of splitInChunks(paths, MAX_CLI_LENGTH)) { + await this.run([...args, '--', ...chunk]); + } + } else { + await this.run([...args, '--', '.']); + } } catch (err) { // In case there are merge conflicts to be resolved, git reset will output // some "needs merge" data. We try to get around that. @@ -1975,10 +1974,10 @@ export class Repository { } async updateSubmodules(paths: string[]): Promise { - const args = ['submodule', 'update', '--']; + const args = ['submodule', 'update']; for (const chunk of splitInChunks(paths.map(sanitizePath), MAX_CLI_LENGTH)) { - await this.run([...args, ...chunk]); + await this.run([...args, '--', ...chunk]); } } diff --git a/extensions/json/package.json b/extensions/json/package.json index 901584e1d90..af713956bfd 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -26,6 +26,7 @@ ".webmanifest", ".js.map", ".css.map", + ".ts.map", ".har", ".jslintrc", ".jsonld" diff --git a/extensions/json/test/colorize-results/test_json.json b/extensions/json/test/colorize-results/test_json.json index fc3dec21721..6f94bec76e6 100644 --- a/extensions/json/test/colorize-results/test_json.json +++ b/extensions/json/test/colorize-results/test_json.json @@ -389,7 +389,7 @@ "t": "source.json meta.structure.dictionary.json meta.structure.dictionary.value.json meta.structure.dictionary.json meta.structure.dictionary.value.json string.quoted.double.json constant.character.escape.json", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -1165,4 +1165,4 @@ "hc_black": "default: #FFFFFF" } } -] +] \ No newline at end of file diff --git a/extensions/make/test/colorize-results/makefile.json b/extensions/make/test/colorize-results/makefile.json index 616de8fb8e0..40adcc74122 100644 --- a/extensions/make/test/colorize-results/makefile.json +++ b/extensions/make/test/colorize-results/makefile.json @@ -136,7 +136,7 @@ "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" @@ -279,7 +279,7 @@ "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" @@ -323,7 +323,7 @@ "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "comment: #6A9955", "light_vs": "comment: #008000", "hc_black": "constant.character: #569CD6" @@ -378,7 +378,7 @@ "t": "source.makefile comment.line.number-sign.makefile constant.character.escape.continuation.makefile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "comment: #6A9955", "light_vs": "comment: #008000", "hc_black": "constant.character: #569CD6" @@ -554,7 +554,7 @@ "t": "source.makefile meta.scope.target.makefile meta.scope.prerequisites.makefile constant.character.escape.continuation.makefile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" @@ -884,7 +884,7 @@ "t": "source.makefile meta.scope.recipe.makefile constant.character.escape.continuation.makefile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" @@ -3029,7 +3029,7 @@ "t": "source.makefile constant.character.escape.continuation.makefile", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", "hc_black": "constant.character: #569CD6" diff --git a/extensions/perl/test/colorize-results/test2_pl.json b/extensions/perl/test/colorize-results/test2_pl.json index 99e22463982..6fc00b0b064 100644 --- a/extensions/perl/test/colorize-results/test2_pl.json +++ b/extensions/perl/test/colorize-results/test2_pl.json @@ -1302,7 +1302,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1324,7 +1324,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1346,7 +1346,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -1775,7 +1775,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" diff --git a/extensions/perl/test/colorize-results/test_pl.json b/extensions/perl/test/colorize-results/test_pl.json index ecfd9660ad8..e47c0f95e84 100644 --- a/extensions/perl/test/colorize-results/test_pl.json +++ b/extensions/perl/test/colorize-results/test_pl.json @@ -389,7 +389,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -411,7 +411,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -433,7 +433,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -455,7 +455,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -477,7 +477,7 @@ "t": "source.perl string.regexp.find.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -675,7 +675,7 @@ "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -950,7 +950,7 @@ "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -1445,7 +1445,7 @@ "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -2281,7 +2281,7 @@ "t": "source.perl string.quoted.double.perl constant.character.escape.perl", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" diff --git a/extensions/php/test/colorize-results/issue-28354_php.json b/extensions/php/test/colorize-results/issue-28354_php.json index 27983076fa7..eb36ede3a4e 100644 --- a/extensions/php/test/colorize-results/issue-28354_php.json +++ b/extensions/php/test/colorize-results/issue-28354_php.json @@ -279,7 +279,7 @@ "t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -378,7 +378,7 @@ "t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php string.quoted.single.php constant.character.escape.php", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" diff --git a/extensions/python/test/colorize-results/test-freeze-56377_py.json b/extensions/python/test/colorize-results/test-freeze-56377_py.json index 5038c289809..3eb0f85a2a1 100644 --- a/extensions/python/test/colorize-results/test-freeze-56377_py.json +++ b/extensions/python/test/colorize-results/test-freeze-56377_py.json @@ -565,7 +565,7 @@ "t": "source.python string.quoted.single.python constant.character.escape.python", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" diff --git a/extensions/ruby/test/colorize-results/test_rb.json b/extensions/ruby/test/colorize-results/test_rb.json index 8679ef23528..09380f91dce 100644 --- a/extensions/ruby/test/colorize-results/test_rb.json +++ b/extensions/ruby/test/colorize-results/test_rb.json @@ -2501,7 +2501,7 @@ "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -2523,7 +2523,7 @@ "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -2545,7 +2545,7 @@ "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" @@ -2578,7 +2578,7 @@ "t": "source.ruby string.regexp.classic.ruby meta.group.regexp.ruby meta.group.regexp.ruby constant.character.escape.ruby", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string.regexp: #D16969", "light_vs": "string.regexp: #811F3F", "hc_black": "constant.character: #569CD6" diff --git a/extensions/scss/test/colorize-results/test_scss.json b/extensions/scss/test/colorize-results/test_scss.json index a95d72d9e16..5841c3b8e3f 100644 --- a/extensions/scss/test/colorize-results/test_scss.json +++ b/extensions/scss/test/colorize-results/test_scss.json @@ -20761,7 +20761,7 @@ "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -20882,7 +20882,7 @@ "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.single.scss constant.character.escape.scss", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -20959,7 +20959,7 @@ "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-value.scss string.quoted.double.scss constant.character.escape.scss", "r": { "dark_plus": "constant.character.escape: #D7BA7D", - "light_plus": "constant.character.escape: #FF0000", + "light_plus": "constant.character.escape: #EE0000", "dark_vs": "string: #CE9178", "light_vs": "string: #A31515", "hc_black": "constant.character: #569CD6" @@ -21020,4 +21020,4 @@ "hc_black": "comment: #7CA668" } } -] +] \ No newline at end of file diff --git a/extensions/search-result/syntaxes/generateTMLanguage.js b/extensions/search-result/syntaxes/generateTMLanguage.js index 23e0615a718..eac084ddbc1 100644 --- a/extensions/search-result/syntaxes/generateTMLanguage.js +++ b/extensions/search-result/syntaxes/generateTMLanguage.js @@ -12,7 +12,7 @@ const mappings = [ ['css', 'source.css'], ['dart', 'source.dart'], ['diff', 'source.diff'], - ['dockerfile', 'source.dockerfile', '(?:dockerfile|Dockerfile)'], + ['dockerfile', 'source.dockerfile', '(?:dockerfile|Dockerfile|containerfile|Containerfile)'], ['fs', 'source.fsharp'], ['go', 'source.go'], ['groovy', 'source.groovy'], diff --git a/extensions/theme-defaults/themes/light_plus.json b/extensions/theme-defaults/themes/light_plus.json index 00c2a6cb470..63e97356983 100644 --- a/extensions/theme-defaults/themes/light_plus.json +++ b/extensions/theme-defaults/themes/light_plus.json @@ -169,7 +169,7 @@ "keyword.control.anchor.regexp" ], "settings": { - "foreground": "#ff0000" + "foreground": "#EE0000" } }, { @@ -181,7 +181,7 @@ { "scope": "constant.character.escape", "settings": { - "foreground": "#ff0000" + "foreground": "#EE0000" } }, { diff --git a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json index 8b1fe2dd80e..935573463ee 100644 --- a/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json +++ b/extensions/theme-monokai-dimmed/themes/dimmed-monokai-color-theme.json @@ -42,7 +42,23 @@ "pickerGroup.foreground": "#b0b0b0", "terminal.ansiWhite": "#ffffff", "inputOption.activeBorder": "#3655b5", - "focusBorder": "#3655b5" + "focusBorder": "#3655b5", + "terminal.ansiBlack": "#1e1e1e", + "terminal.ansiRed": "#C4265E", // the bright color with ~75% transparent on the background + "terminal.ansiGreen": "#86B42B", + "terminal.ansiYellow": "#B3B42B", + "terminal.ansiBlue": "#6A7EC8", + "terminal.ansiMagenta": "#8C6BC8", + "terminal.ansiCyan": "#56ADBC", + "terminal.ansiWhite": "#e3e3dd", + "terminal.ansiBrightBlack": "#666666", + "terminal.ansiBrightRed": "#f92672", + "terminal.ansiBrightGreen": "#A6E22E", + "terminal.ansiBrightYellow": "#e2e22e", // hue shifted #A6E22E + "terminal.ansiBrightBlue": "#819aff", // hue shifted #AE81FF + "terminal.ansiBrightMagenta": "#AE81FF", + "terminal.ansiBrightCyan": "#66D9EF", + "terminal.ansiBrightWhite": "#f8f8f2" }, "tokenColors": [ { diff --git a/extensions/theme-seti/cgmanifest.json b/extensions/theme-seti/cgmanifest.json index a3df8c6b322..b3bb41d3eb9 100644 --- a/extensions/theme-seti/cgmanifest.json +++ b/extensions/theme-seti/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "seti-ui", "repositoryUrl": "https://github.com/jesseweed/seti-ui", - "commitHash": "8f22764c37feb7f706465f5186132111a2401b6b" + "commitHash": "f3b2775662b0075aab56e5f0c03269f21f3f0f30" } }, "version": "0.1.0" diff --git a/extensions/theme-seti/icons/seti.woff b/extensions/theme-seti/icons/seti.woff index b4b8366f165..5dc3bb8d9b0 100644 Binary files a/extensions/theme-seti/icons/seti.woff and b/extensions/theme-seti/icons/seti.woff differ diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index efa15be7bca..a1f5817da5c 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -1030,12 +1030,6 @@ "fontCharacter": "\\E074", "fontColor": "#cc3e44" }, - "_rmd_light": { - "fontColor": "#498ba7" - }, - "_rmd": { - "fontColor": "#519aba" - }, "_rollup_light": { "fontCharacter": "\\E075", "fontColor": "#b8383d" @@ -1483,7 +1477,7 @@ "test.tsx": "_react_2", "re": "_reasonml", "r": "_R", - "rmd": "_rmd", + "rmd": "_R", "erb": "_html_erb", "erb.html": "_html_erb", "html.erb": "_html_erb", @@ -1678,7 +1672,7 @@ "sql": "_db", "swift": "_swift", "typescript": "_typescript", - "typescriptreact": "_react", + "typescriptreact": "_typescript", "xml": "_xml", "yaml": "_yml", "argdown": "_argdown", @@ -1811,7 +1805,7 @@ "test.tsx": "_react_2_light", "re": "_reasonml_light", "r": "_R_light", - "rmd": "_rmd_light", + "rmd": "_R_light", "erb": "_html_erb_light", "erb.html": "_html_erb_light", "html.erb": "_html_erb_light", @@ -1949,7 +1943,7 @@ "sql": "_db_light", "swift": "_swift_light", "typescript": "_typescript_light", - "typescriptreact": "_react_light", + "typescriptreact": "_typescript_light", "xml": "_xml_light", "yaml": "_yml_light", "argdown": "_argdown_light", @@ -2030,5 +2024,5 @@ "npm-debug.log": "_npm_ignored_light" } }, - "version": "https://github.com/jesseweed/seti-ui/commit/8f22764c37feb7f706465f5186132111a2401b6b" + "version": "https://github.com/jesseweed/seti-ui/commit/f3b2775662b0075aab56e5f0c03269f21f3f0f30" } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/tsServer/spawner.ts b/extensions/typescript-language-features/src/tsServer/spawner.ts index 89e4261fb05..99318d9940d 100644 --- a/extensions/typescript-language-features/src/tsServer/spawner.ts +++ b/extensions/typescript-language-features/src/tsServer/spawner.ts @@ -110,9 +110,10 @@ export class TypeScriptServerSpawner { private getForkOptions(kind: ServerKind, configuration: TypeScriptServiceConfiguration) { const debugPort = TypeScriptServerSpawner.getDebugPort(kind); + const inspectFlag = process.env['TSS_DEBUG_BRK'] ? '--inspect-brk' : '--inspect'; const tsServerForkOptions: electron.ForkOptions = { execArgv: [ - ...(debugPort ? [`--inspect=${debugPort}`] : []), + ...(debugPort ? [`${inspectFlag}=${debugPort}`] : []), ...(configuration.maxTsServerMemory ? [`--max-old-space-size=${configuration.maxTsServerMemory}`] : []) ] }; @@ -200,7 +201,7 @@ export class TypeScriptServerSpawner { // We typically only want to debug the main semantic server return undefined; } - const value = process.env['TSS_DEBUG']; + const value = process.env['TSS_DEBUG_BRK'] || process.env['TSS_DEBUG']; if (value) { const port = parseInt(value); if (!isNaN(port)) { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts index 9c30a873e85..8c407fb6c8b 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts @@ -29,31 +29,34 @@ suite('vscode API - languages', () => { const doc = await vscode.workspace.openTextDocument(file); const langIdNow = doc.languageId; let clock = 0; + const disposables: vscode.Disposable[] = []; let close = new Promise(resolve => { - vscode.workspace.onDidCloseTextDocument(e => { + disposables.push(vscode.workspace.onDidCloseTextDocument(e => { if (e === doc) { assert.equal(doc.languageId, langIdNow); assert.equal(clock, 0); clock += 1; resolve(); } - }); + })); }); let open = new Promise(resolve => { - vscode.workspace.onDidOpenTextDocument(e => { + disposables.push(vscode.workspace.onDidOpenTextDocument(e => { if (e === doc) { // same instance! assert.equal(doc.languageId, 'json'); assert.equal(clock, 1); clock += 1; resolve(); } - }); + })); }); let change = vscode.languages.setTextDocumentLanguage(doc, 'json'); await Promise.all([change, close, open]); assert.equal(clock, 2); assert.equal(doc.languageId, 'json'); + disposables.forEach(disposable => disposable.dispose()); + disposables.length = 0; }); test('setTextDocumentLanguage -> error when language does not exist', async function () { diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index 19d9e97a2c4..ec6eab2d898 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -318,10 +318,14 @@ suite('notebook workflow', () => { // ---- move up and down ---- // await vscode.commands.executeCommand('notebook.cell.moveDown'); + assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(vscode.notebook.activeNotebookEditor!.selection!), 1, + `first move down, active cell ${vscode.notebook.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.notebook.activeNotebookEditor!.selection!.source}`); + await vscode.commands.executeCommand('notebook.cell.moveDown'); activeCell = vscode.notebook.activeNotebookEditor!.selection; - assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2); + assert.equal(vscode.notebook.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2, + `second move down, active cell ${vscode.notebook.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.notebook.activeNotebookEditor!.selection!.source}`); assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[0].source, 'test'); assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[1].source, ''); assert.equal(vscode.notebook.activeNotebookEditor!.document.cells[2].source, 'test'); diff --git a/package.json b/package.json index 16103d731fa..932f4abcc31 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "8.3.0", + "electron": "7.2.4", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "event-stream": "3.3.4", diff --git a/scripts/code-web.js b/scripts/code-web.js index b7441ea0158..b208a1e908e 100755 --- a/scripts/code-web.js +++ b/scripts/code-web.js @@ -148,11 +148,6 @@ async function handleRoot(req, res) { if (packageJSON.main && packageJSON.name !== 'vscode-web-playground') { return; // unsupported } - - if (packageJSON.name === 'scss') { - return; // seems to fail to JSON.parse()?! - } - packageJSON.extensionKind = ['web']; // enable for Web mapExtensionFolderToExtensionPackageJSON.set(extensionFolder, packageJSON); @@ -171,11 +166,10 @@ async function handleRoot(req, res) { }); }); + const webConfiguration = escapeAttribute(JSON.stringify({ staticExtensions, folderUri: { scheme: 'memfs', path: `/sample-folder` }})); + const data = (await util.promisify(fs.readFile)(WEB_MAIN)).toString() - .replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({ - staticExtensions, - folderUri: { scheme: 'memfs', path: `/sample-folder` } - }))) + .replace('{{WORKBENCH_WEB_CONFIGURATION}}', () => webConfiguration) // use a replace function to avoid that regexp replace patterns ($&, $0, ...) are applied .replace('{{WEBVIEW_ENDPOINT}}', '') .replace('{{REMOTE_USER_DATA_URI}}', ''); diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index da658dd0d57..143ab78cb67 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -111,7 +111,10 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende } href = _href(href, false); if (options.baseUrl) { - href = resolvePath(options.baseUrl, href).toString(); + const hasScheme = /^\w[\w\d+.-]*:/.test(href); + if (!hasScheme) { + href = resolvePath(options.baseUrl, href).toString(); + } } title = removeMarkdownEscapes(title); href = removeMarkdownEscapes(href); diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index b7c858d1ed2..84978eab45d 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -9,8 +9,8 @@ import { Gesture, EventType as TouchEventType, GestureEvent } from 'vs/base/brow import * as DOM from 'vs/base/browser/dom'; import { Event, Emitter } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; -import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; -import { ScrollEvent, ScrollbarVisibility, INewScrollDimensions } from 'vs/base/common/scrollable'; +import { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { ScrollEvent, ScrollbarVisibility, INewScrollDimensions, Scrollable } from 'vs/base/common/scrollable'; import { RangeMap, shift } from './rangeMap'; import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListTouchEvent, IListGestureEvent, IListDragEvent, IListDragAndDrop, ListDragOverEffect } from './list'; import { RowCache, IRow } from './rowCache'; @@ -48,7 +48,12 @@ export interface IListViewAccessibilityProvider { isChecked?(element: T): boolean | undefined; } -export interface IListViewOptions { +export interface IListViewOptionsUpdate { + readonly additionalScrollHeight?: number; + readonly smoothScrolling?: boolean; +} + +export interface IListViewOptions extends IListViewOptionsUpdate { readonly dnd?: IListViewDragAndDrop; readonly useShadows?: boolean; readonly verticalScrollMode?: ScrollbarVisibility; @@ -58,7 +63,6 @@ export interface IListViewOptions { readonly mouseSupport?: boolean; readonly horizontalScrolling?: boolean; readonly accessibilityProvider?: IListViewAccessibilityProvider; - readonly additionalScrollHeight?: number; readonly transformOptimization?: boolean; } @@ -204,7 +208,8 @@ export class ListView implements ISpliceable, IDisposable { private lastRenderHeight: number; private renderWidth = 0; private rowsContainer: HTMLElement; - private scrollableElement: ScrollableElement; + private scrollable: Scrollable; + private scrollableElement: SmoothScrollableElement; private _scrollHeight: number = 0; private scrollableElementUpdateDisposable: IDisposable | null = null; private scrollableElementWidthDelayer = new Delayer(50); @@ -285,12 +290,13 @@ export class ListView implements ISpliceable, IDisposable { this.disposables.add(Gesture.addTarget(this.rowsContainer)); - this.scrollableElement = this.disposables.add(new ScrollableElement(this.rowsContainer, { + this.scrollable = new Scrollable(getOrDefault(options, o => o.smoothScrolling, false) ? 125 : 0, cb => DOM.scheduleAtNextAnimationFrame(cb)); + this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, { alwaysConsumeMouseWheel: true, horizontal: this.horizontalScrolling ? ScrollbarVisibility.Auto : ScrollbarVisibility.Hidden, vertical: getOrDefault(options, o => o.verticalScrollMode, DefaultOptions.verticalScrollMode), - useShadows: getOrDefault(options, o => o.useShadows, DefaultOptions.useShadows) - })); + useShadows: getOrDefault(options, o => o.useShadows, DefaultOptions.useShadows), + }, this.scrollable)); this.domNode.appendChild(this.scrollableElement.getDomNode()); container.appendChild(this.domNode); @@ -320,6 +326,10 @@ export class ListView implements ISpliceable, IDisposable { if (options.additionalScrollHeight !== undefined) { this.additionalScrollHeight = options.additionalScrollHeight; } + + if (options.smoothScrolling !== undefined) { + this.scrollable.setSmoothScrollDuration(options.smoothScrolling ? 125 : 0); + } } triggerScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) { diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 856b97f1a6a..ca09bbf018a 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -16,7 +16,7 @@ import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardE import { Event, Emitter, EventBufferer } from 'vs/base/common/event'; import { domEvent } from 'vs/base/browser/event'; import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListError, IKeyboardNavigationDelegate } from './list'; -import { ListView, IListViewOptions, IListViewDragAndDrop, IListViewAccessibilityProvider } from './listView'; +import { ListView, IListViewOptions, IListViewDragAndDrop, IListViewAccessibilityProvider, IListViewOptionsUpdate } from './listView'; import { Color } from 'vs/base/common/color'; import { mixin } from 'vs/base/common/objects'; import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable'; @@ -1107,10 +1107,9 @@ class ListViewDragAndDrop implements IListViewDragAndDrop { } } -export interface IListOptionsUpdate { +export interface IListOptionsUpdate extends IListViewOptionsUpdate { readonly enableKeyboardNavigation?: boolean; readonly automaticKeyboardNavigation?: boolean; - readonly additionalScrollHeight?: number; } export class List implements ISpliceable, IDisposable { @@ -1288,9 +1287,7 @@ export class List implements ISpliceable, IDisposable { this.typeLabelController.updateOptions(this._options); } - if (optionsUpdate.additionalScrollHeight !== undefined) { - this.view.updateOptions(optionsUpdate); - } + this.view.updateOptions(optionsUpdate); } get options(): IListOptions { diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index 8612b5b1b84..ed48038df11 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -41,6 +41,7 @@ export interface IMenuOptions { enableMnemonics?: boolean; anchorAlignment?: AnchorAlignment; expandDirection?: Direction; + useEventAsContext?: boolean; } export interface IMenuStyles { @@ -316,7 +317,7 @@ export class Menu extends ActionBar { return menuActionViewItem; } else { - const menuItemOptions: IMenuItemOptions = { enableMnemonics: options.enableMnemonics }; + const menuItemOptions: IMenuItemOptions = { enableMnemonics: options.enableMnemonics, useEventAsContext: options.useEventAsContext }; if (options.getKeyBinding) { const keybinding = options.getKeyBinding(action); if (keybinding) { diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index 463073dc0a7..f4506d877b5 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -945,7 +945,8 @@ export class MenuBar extends Disposable { actionRunner: this.actionRunner, enableMnemonics: this.options.alwaysOnMnemonics || (this.mnemonicsInUse && this.options.enableMnemonics), ariaLabel: withNullAsUndefined(customMenu.buttonElement.getAttribute('aria-label')), - expandDirection: this.options.compactMode !== undefined ? this.options.compactMode : Direction.Right + expandDirection: this.options.compactMode !== undefined ? this.options.compactMode : Direction.Right, + useEventAsContext: true }; let menuWidget = this._register(new Menu(menuHolder, customMenu.actions, menuOptions)); diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index da2f2b6cee8..933af1512ed 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -533,6 +533,14 @@ export class SmoothScrollableElement extends AbstractScrollableElement { super(element, options, scrollable); } + public setScrollPosition(update: INewScrollPosition): void { + this._scrollable.setScrollPositionNow(update); + } + + public getScrollPosition(): IScrollPosition { + return this._scrollable.getCurrentScrollPosition(); + } + } export class DomScrollableElement extends ScrollableElement { diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index 4924646f11c..50558044d09 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -727,7 +727,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi mouseSupport: false, accessibilityProvider: { getAriaLabel: (element) => element.text, - getWidgetAriaLabel: () => localize('selectBox', "Select Box"), + getWidgetAriaLabel: () => localize({ key: 'selectBox', comment: ['Behave like native select dropdown element.'] }, "Select Box"), getRole: () => 'option', getWidgetRole: () => 'listbox' } diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index a71e4d6ae48..f19a1cc4cad 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -962,6 +962,7 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions { readonly simpleKeyboardNavigation?: boolean; readonly filterOnType?: boolean; readonly openOnSingleClick?: boolean; + readonly smoothScrolling?: boolean; } export interface IAbstractTreeOptions extends IAbstractTreeOptionsUpdate, IListOptions { @@ -1360,7 +1361,8 @@ export abstract class AbstractTree implements IDisposable this.view.updateOptions({ enableKeyboardNavigation: this._options.simpleKeyboardNavigation, - automaticKeyboardNavigation: this._options.automaticKeyboardNavigation + automaticKeyboardNavigation: this._options.automaticKeyboardNavigation, + smoothScrolling: this._options.smoothScrolling }); if (this.typeFilterController) { diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index 032f447081e..b0bd0ab2799 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -328,8 +328,8 @@ export namespace Event { } export interface NodeEventEmitter { - on(event: string | symbol, listener: Function): this; - removeListener(event: string | symbol, listener: Function): this; + on(event: string | symbol, listener: Function): unknown; + removeListener(event: string | symbol, listener: Function): unknown; } export function fromNodeEventEmitter(emitter: NodeEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event { diff --git a/src/vs/base/common/extpath.ts b/src/vs/base/common/extpath.ts index e064829c5a0..8fe9f9e1c2a 100644 --- a/src/vs/base/common/extpath.ts +++ b/src/vs/base/common/extpath.ts @@ -7,6 +7,7 @@ import { isWindows } from 'vs/base/common/platform'; import { startsWithIgnoreCase, equalsIgnoreCase, rtrim } from 'vs/base/common/strings'; import { CharCode } from 'vs/base/common/charCode'; import { sep, posix, isAbsolute, join, normalize } from 'vs/base/common/path'; +import { isNumber } from 'vs/base/common/types'; export function isPathSeparator(code: number) { return code === CharCode.Slash || code === CharCode.Backslash; @@ -300,3 +301,38 @@ export function indexOfPath(path: string, candidate: string, ignoreCase: boolean return path.indexOf(candidate); } + +export interface IPathWithLineAndColumn { + path: string; + line?: number; + column?: number; +} + +export function parseLineAndColumnAware(rawPath: string): IPathWithLineAndColumn { + const segments = rawPath.split(':'); // C:\file.txt:: + + let path: string | undefined = undefined; + let line: number | undefined = undefined; + let column: number | undefined = undefined; + + segments.forEach(segment => { + const segmentAsNumber = Number(segment); + if (!isNumber(segmentAsNumber)) { + path = !!path ? [path, segment].join(':') : segment; // a colon can well be part of a path (e.g. C:\...) + } else if (line === undefined) { + line = segmentAsNumber; + } else if (column === undefined) { + column = segmentAsNumber; + } + }); + + if (!path) { + throw new Error('Format for `--goto` should be: `FILE:LINE(:COLUMN)`'); + } + + return { + path, + line: line !== undefined ? line : undefined, + column: column !== undefined ? column : line !== undefined ? 1 : undefined // if we have a line, make sure column is also set + }; +} diff --git a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts index 7b43355ed6d..6222be78028 100644 --- a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts @@ -9,10 +9,9 @@ import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_ export function registerContextMenuListener(): void { ipcMain.on(CONTEXT_MENU_CHANNEL, (event: IpcMainEvent, contextMenuId: number, items: ISerializableContextMenuItem[], onClickChannel: string, options?: IPopupOptions) => { const menu = createMenu(event, onClickChannel, items); - const window = BrowserWindow.fromWebContents(event.sender); menu.popup({ - window: window ? window : undefined, + window: BrowserWindow.fromWebContents(event.sender), x: options ? options.x : undefined, y: options ? options.y : undefined, positioningItem: options ? options.positioningItem : undefined, diff --git a/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts similarity index 87% rename from src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts rename to src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts index da008e59930..4b5c3fbdf75 100644 --- a/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ipcRenderer, Event } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { IContextMenuItem, ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions, IContextMenuEvent } from 'vs/base/parts/contextmenu/common/contextmenu'; let contextMenuIdPool = 0; @@ -13,7 +13,7 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void const contextMenuId = contextMenuIdPool++; const onClickChannel = `vscode:onContextMenu${contextMenuId}`; - const onClickChannelHandler = (_event: Event, itemId: number, context: IContextMenuEvent) => { + const onClickChannelHandler = (event: unknown, itemId: number, context: IContextMenuEvent) => { const item = processedItems[itemId]; if (item.click) { item.click(context); @@ -21,7 +21,7 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void }; ipcRenderer.once(onClickChannel, onClickChannelHandler); - ipcRenderer.once(CONTEXT_MENU_CLOSE_CHANNEL, (_event: Event, closedContextMenuId: number) => { + ipcRenderer.once(CONTEXT_MENU_CLOSE_CHANNEL, (event: unknown, closedContextMenuId: number) => { if (closedContextMenuId !== contextMenuId) { return; } diff --git a/src/vs/base/parts/ipc/node/ipc.electron.ts b/src/vs/base/parts/ipc/common/ipc.electron.ts similarity index 83% rename from src/vs/base/parts/ipc/node/ipc.electron.ts rename to src/vs/base/parts/ipc/common/ipc.electron.ts index 09c97ba47b1..516351e1509 100644 --- a/src/vs/base/parts/ipc/node/ipc.electron.ts +++ b/src/vs/base/parts/ipc/common/ipc.electron.ts @@ -8,7 +8,7 @@ import { Event } from 'vs/base/common/event'; import { VSBuffer } from 'vs/base/common/buffer'; export interface Sender { - send(channel: string, msg: Buffer | null): void; + send(channel: string, msg: unknown): void; } export class Protocol implements IMessagePassingProtocol { @@ -17,13 +17,13 @@ export class Protocol implements IMessagePassingProtocol { send(message: VSBuffer): void { try { - this.sender.send('ipc:message', (message.buffer)); + this.sender.send('vscode:message', message.buffer); } catch (e) { // systems are going down } } dispose(): void { - this.sender.send('ipc:disconnect', null); + this.sender.send('vscode:disconnect', null); } -} \ No newline at end of file +} diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index 8acfc6bce4e..411bfe46cca 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -10,7 +10,9 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance import * as errors from 'vs/base/common/errors'; import { VSBuffer } from 'vs/base/common/buffer'; import { getRandomElement } from 'vs/base/common/arrays'; -import { isFunction } from 'vs/base/common/types'; +import { isFunction, isUndefinedOrNull } from 'vs/base/common/types'; +import { revive } from 'vs/base/common/marshalling'; +import { isUpperAsciiLetter } from 'vs/base/common/strings'; /** * An `IChannel` is an abstraction over a collection of commands. @@ -919,3 +921,142 @@ export class StaticRouter implements IClientRouter return await this.route(hub); } } + + +//#region createChannelReceiver / createChannelSender + +/** + * Use both `createChannelReceiver` and `createChannelSender` + * for automated process <=> process communication over methods + * and events. You do not need to spell out each method on both + * sides, a proxy will take care of this. + * + * Rules: + * - if marshalling is enabled, only `URI` and `RegExp` is converted + * automatically for you + * - events must follow the naming convention `onUppercase` + * - `CancellationToken` is currently not supported + * - if a context is provided, you can use `AddFirstParameterToFunctions` + * utility to signal this in the receiving side type + */ + +export interface IBaseChannelOptions { + + /** + * Disables automatic marshalling of `URI`. + * If marshalling is disabled, `UriComponents` + * must be used instead. + */ + disableMarshalling?: boolean; +} + +export interface IChannelReceiverOptions extends IBaseChannelOptions { } + +export function createChannelReceiver(service: unknown, options?: IChannelReceiverOptions): IServerChannel { + const handler = service as { [key: string]: unknown }; + const disableMarshalling = options && options.disableMarshalling; + + // Buffer any event that should be supported by + // iterating over all property keys and finding them + const mapEventNameToEvent = new Map>(); + for (const key in handler) { + if (propertyIsEvent(key)) { + mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event, true)); + } + } + + return new class implements IServerChannel { + + listen(_: unknown, event: string): Event { + const eventImpl = mapEventNameToEvent.get(event); + if (eventImpl) { + return eventImpl as Event; + } + + throw new Error(`Event not found: ${event}`); + } + + call(_: unknown, command: string, args?: any[]): Promise { + const target = handler[command]; + if (typeof target === 'function') { + + // Revive unless marshalling disabled + if (!disableMarshalling && Array.isArray(args)) { + for (let i = 0; i < args.length; i++) { + args[i] = revive(args[i]); + } + } + + return target.apply(handler, args); + } + + throw new Error(`Method not found: ${command}`); + } + }; +} + +export interface IChannelSenderOptions extends IBaseChannelOptions { + + /** + * If provided, will add the value of `context` + * to each method call to the target. + */ + context?: unknown; + + /** + * If provided, will not proxy any of the properties + * that are part of the Map but rather return that value. + */ + properties?: Map; +} + +export function createChannelSender(channel: IChannel, options?: IChannelSenderOptions): T { + const disableMarshalling = options && options.disableMarshalling; + + return new Proxy({}, { + get(_target: T, propKey: PropertyKey) { + if (typeof propKey === 'string') { + + // Check for predefined values + if (options?.properties?.has(propKey)) { + return options.properties.get(propKey); + } + + // Event + if (propertyIsEvent(propKey)) { + return channel.listen(propKey); + } + + // Function + return async function (...args: any[]) { + + // Add context if any + let methodArgs: any[]; + if (options && !isUndefinedOrNull(options.context)) { + methodArgs = [options.context, ...args]; + } else { + methodArgs = args; + } + + const result = await channel.call(propKey, methodArgs); + + // Revive unless marshalling disabled + if (!disableMarshalling) { + return revive(result); + } + + return result; + }; + } + + throw new Error(`Property not found: ${String(propKey)}`); + } + }) as T; +} + +function propertyIsEvent(name: string): boolean { + // Assume a property is an event if it has a form of "onSomething" + return name[0] === 'o' && name[1] === 'n' && isUpperAsciiLetter(name.charCodeAt(2)); +} + +//#endregion diff --git a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts index bac2223ede6..b84a1d653dc 100644 --- a/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts +++ b/src/vs/base/parts/ipc/electron-main/ipc.electron-main.ts @@ -5,7 +5,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/common/ipc'; -import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron'; +import { Protocol } from 'vs/base/parts/ipc/common/ipc.electron'; import { ipcMain, WebContents } from 'electron'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { VSBuffer } from 'vs/base/common/buffer'; @@ -26,7 +26,7 @@ export class Server extends IPCServer { private static readonly Clients = new Map(); private static getOnDidClientConnect(): Event { - const onHello = Event.fromNodeEventEmitter(ipcMain, 'ipc:hello', ({ sender }) => sender); + const onHello = Event.fromNodeEventEmitter(ipcMain, 'vscode:hello', ({ sender }) => sender); return Event.map(onHello, webContents => { const id = webContents.id; @@ -39,8 +39,8 @@ export class Server extends IPCServer { const onDidClientReconnect = new Emitter(); Server.Clients.set(id, toDisposable(() => onDidClientReconnect.fire())); - const onMessage = createScopedOnMessageEvent(id, 'ipc:message') as Event; - const onDidClientDisconnect = Event.any(Event.signal(createScopedOnMessageEvent(id, 'ipc:disconnect')), onDidClientReconnect.event); + const onMessage = createScopedOnMessageEvent(id, 'vscode:message') as Event; + const onDidClientDisconnect = Event.any(Event.signal(createScopedOnMessageEvent(id, 'vscode:disconnect')), onDidClientReconnect.event); const protocol = new Protocol(webContents, onMessage); return { protocol, onDidClientDisconnect }; diff --git a/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts b/src/vs/base/parts/ipc/electron-sandbox/ipc.electron-sandbox.ts similarity index 80% rename from src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts rename to src/vs/base/parts/ipc/electron-sandbox/ipc.electron-sandbox.ts index 2690300b83a..19ca487c890 100644 --- a/src/vs/base/parts/ipc/electron-browser/ipc.electron-browser.ts +++ b/src/vs/base/parts/ipc/electron-sandbox/ipc.electron-sandbox.ts @@ -5,18 +5,18 @@ import { Event } from 'vs/base/common/event'; import { IPCClient } from 'vs/base/parts/ipc/common/ipc'; -import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron'; -import { ipcRenderer } from 'electron'; +import { Protocol } from 'vs/base/parts/ipc/common/ipc.electron'; import { IDisposable } from 'vs/base/common/lifecycle'; import { VSBuffer } from 'vs/base/common/buffer'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; export class Client extends IPCClient implements IDisposable { private protocol: Protocol; private static createProtocol(): Protocol { - const onMessage = Event.fromNodeEventEmitter(ipcRenderer, 'ipc:message', (_, message: Buffer) => VSBuffer.wrap(message)); - ipcRenderer.send('ipc:hello'); + const onMessage = Event.fromNodeEventEmitter(ipcRenderer, 'vscode:message', (_, message) => VSBuffer.wrap(message)); + ipcRenderer.send('vscode:hello'); return new Protocol(ipcRenderer, onMessage); } @@ -29,4 +29,4 @@ export class Client extends IPCClient implements IDisposable { dispose(): void { this.protocol.dispose(); } -} \ No newline at end of file +} diff --git a/src/vs/base/parts/ipc/node/ipc.ts b/src/vs/base/parts/ipc/node/ipc.ts deleted file mode 100644 index 631e5139133..00000000000 --- a/src/vs/base/parts/ipc/node/ipc.ts +++ /dev/null @@ -1,133 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Event } from 'vs/base/common/event'; -import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { revive } from 'vs/base/common/marshalling'; -import { isUndefinedOrNull } from 'vs/base/common/types'; -import { isUpperAsciiLetter } from 'vs/base/common/strings'; - -/** - * Use both `createChannelReceiver` and `createChannelSender` - * for automated process <=> process communication over methods - * and events. You do not need to spell out each method on both - * sides, a proxy will take care of this. - * - * Rules: - * - if marshalling is enabled, only `URI` and `RegExp` is converted - * automatically for you - * - events must follow the naming convention `onUppercase` - * - `CancellationToken` is currently not supported - * - if a context is provided, you can use `AddFirstParameterToFunctions` - * utility to signal this in the receiving side type - */ - -export interface IBaseChannelOptions { - - /** - * Disables automatic marshalling of `URI`. - * If marshalling is disabled, `UriComponents` - * must be used instead. - */ - disableMarshalling?: boolean; -} - -export interface IChannelReceiverOptions extends IBaseChannelOptions { } - -export function createChannelReceiver(service: unknown, options?: IChannelReceiverOptions): IServerChannel { - const handler = service as { [key: string]: unknown }; - const disableMarshalling = options && options.disableMarshalling; - - // Buffer any event that should be supported by - // iterating over all property keys and finding them - const mapEventNameToEvent = new Map>(); - for (const key in handler) { - if (propertyIsEvent(key)) { - mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event, true)); - } - } - - return new class implements IServerChannel { - - listen(_: unknown, event: string): Event { - const eventImpl = mapEventNameToEvent.get(event); - if (eventImpl) { - return eventImpl as Event; - } - - throw new Error(`Event not found: ${event}`); - } - - call(_: unknown, command: string, args?: any[]): Promise { - const target = handler[command]; - if (typeof target === 'function') { - - // Revive unless marshalling disabled - if (!disableMarshalling && Array.isArray(args)) { - for (let i = 0; i < args.length; i++) { - args[i] = revive(args[i]); - } - } - - return target.apply(handler, args); - } - - throw new Error(`Method not found: ${command}`); - } - }; -} - -export interface IChannelSenderOptions extends IBaseChannelOptions { - - /** - * If provided, will add the value of `context` - * to each method call to the target. - */ - context?: unknown; -} - -export function createChannelSender(channel: IChannel, options?: IChannelSenderOptions): T { - const disableMarshalling = options && options.disableMarshalling; - - return new Proxy({}, { - get(_target: T, propKey: PropertyKey) { - if (typeof propKey === 'string') { - - // Event - if (propertyIsEvent(propKey)) { - return channel.listen(propKey); - } - - // Function - return async function (...args: any[]) { - - // Add context if any - let methodArgs: any[]; - if (options && !isUndefinedOrNull(options.context)) { - methodArgs = [options.context, ...args]; - } else { - methodArgs = args; - } - - const result = await channel.call(propKey, methodArgs); - - // Revive unless marshalling disabled - if (!disableMarshalling) { - return revive(result); - } - - return result; - }; - } - - throw new Error(`Property not found: ${String(propKey)}`); - } - }) as T; -} - -function propertyIsEvent(name: string): boolean { - // Assume a property is an event if it has a form of "onSomething" - return name[0] === 'o' && name[1] === 'n' && isUpperAsciiLetter(name.charCodeAt(2)); -} diff --git a/src/vs/base/parts/ipc/test/node/ipc.test.ts b/src/vs/base/parts/ipc/test/common/ipc.test.ts similarity index 95% rename from src/vs/base/parts/ipc/test/node/ipc.test.ts rename to src/vs/base/parts/ipc/test/common/ipc.test.ts index 3539f5dea8c..8ed0f3797f1 100644 --- a/src/vs/base/parts/ipc/test/node/ipc.test.ts +++ b/src/vs/base/parts/ipc/test/common/ipc.test.ts @@ -4,8 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient } from 'vs/base/parts/ipc/common/ipc'; -import { createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/node/ipc'; +import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import { Emitter, Event } from 'vs/base/common/event'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { canceled } from 'vs/base/common/errors'; @@ -103,7 +102,7 @@ interface ITestService { error(message: string): Promise; neverComplete(): Promise; neverCompleteCT(cancellationToken: CancellationToken): Promise; - buffersLength(buffers: Buffer[]): Promise; + buffersLength(buffers: VSBuffer[]): Promise; marshall(uri: URI): Promise; context(): Promise; @@ -135,8 +134,8 @@ class TestService implements ITestService { return new Promise((_, e) => cancellationToken.onCancellationRequested(() => e(canceled()))); } - buffersLength(buffers: Buffer[]): Promise { - return Promise.resolve(buffers.reduce((r, b) => r + b.length, 0)); + buffersLength(buffers: VSBuffer[]): Promise { + return Promise.resolve(buffers.reduce((r, b) => r + b.buffer.length, 0)); } ping(msg: string): void { @@ -199,7 +198,7 @@ class TestChannelClient implements ITestService { return this.channel.call('neverCompleteCT', undefined, cancellationToken); } - buffersLength(buffers: Buffer[]): Promise { + buffersLength(buffers: VSBuffer[]): Promise { return this.channel.call('buffersLength', buffers); } @@ -317,7 +316,7 @@ suite('Base IPC', function () { }); test('buffers in arrays', async function () { - const r = await ipcService.buffersLength([Buffer.allocUnsafe(2), Buffer.allocUnsafe(3)]); + const r = await ipcService.buffersLength([VSBuffer.alloc(2), VSBuffer.alloc(3)]); return assert.equal(r, 5); }); }); @@ -383,7 +382,7 @@ suite('Base IPC', function () { }); test('buffers in arrays', async function () { - const r = await ipcService.buffersLength([Buffer.allocUnsafe(2), Buffer.allocUnsafe(3)]); + const r = await ipcService.buffersLength([VSBuffer.alloc(2), VSBuffer.alloc(3)]); return assert.equal(r, 5); }); }); diff --git a/src/vs/base/parts/sandbox/common/electronTypes.ts b/src/vs/base/parts/sandbox/common/electronTypes.ts new file mode 100644 index 00000000000..651a9d575ef --- /dev/null +++ b/src/vs/base/parts/sandbox/common/electronTypes.ts @@ -0,0 +1,249 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +// ####################################################################### +// ### ### +// ### electron.d.ts types we need in a common layer for reuse ### +// ### (copied from Electron 7.x) ### +// ### ### +// ####################################################################### + + +export interface MessageBoxOptions { + /** + * Can be `"none"`, `"info"`, `"error"`, `"question"` or `"warning"`. On Windows, + * `"question"` displays the same icon as `"info"`, unless you set an icon using + * the `"icon"` option. On macOS, both `"warning"` and `"error"` display the same + * warning icon. + */ + type?: string; + /** + * Array of texts for buttons. On Windows, an empty array will result in one button + * labeled "OK". + */ + buttons?: string[]; + /** + * Index of the button in the buttons array which will be selected by default when + * the message box opens. + */ + defaultId?: number; + /** + * Title of the message box, some platforms will not show it. + */ + title?: string; + /** + * Content of the message box. + */ + message: string; + /** + * Extra information of the message. + */ + detail?: string; + /** + * If provided, the message box will include a checkbox with the given label. + */ + checkboxLabel?: string; + /** + * Initial checked state of the checkbox. `false` by default. + */ + checkboxChecked?: boolean; + // icon?: NativeImage; + /** + * The index of the button to be used to cancel the dialog, via the `Esc` key. By + * default this is assigned to the first button with "cancel" or "no" as the label. + * If no such labeled buttons exist and this option is not set, `0` will be used as + * the return value. + */ + cancelId?: number; + /** + * On Windows Electron will try to figure out which one of the `buttons` are common + * buttons (like "Cancel" or "Yes"), and show the others as command links in the + * dialog. This can make the dialog appear in the style of modern Windows apps. If + * you don't like this behavior, you can set `noLink` to `true`. + */ + noLink?: boolean; + /** + * Normalize the keyboard access keys across platforms. Default is `false`. + * Enabling this assumes `&` is used in the button labels for the placement of the + * keyboard shortcut access key and labels will be converted so they work correctly + * on each platform, `&` characters are removed on macOS, converted to `_` on + * Linux, and left untouched on Windows. For example, a button label of `Vie&w` + * will be converted to `Vie_w` on Linux and `View` on macOS and can be selected + * via `Alt-W` on Windows and Linux. + */ + normalizeAccessKeys?: boolean; +} + +export interface MessageBoxReturnValue { + /** + * The index of the clicked button. + */ + response: number; + /** + * The checked state of the checkbox if `checkboxLabel` was set. Otherwise `false`. + */ + checkboxChecked: boolean; +} + +export interface OpenDevToolsOptions { + /** + * Opens the devtools with specified dock state, can be `right`, `bottom`, + * `undocked`, `detach`. Defaults to last used dock state. In `undocked` mode it's + * possible to dock back. In `detach` mode it's not. + */ + mode: ('right' | 'bottom' | 'undocked' | 'detach'); + /** + * Whether to bring the opened devtools window to the foreground. The default is + * `true`. + */ + activate?: boolean; +} + +export interface SaveDialogOptions { + title?: string; + /** + * Absolute directory path, absolute file path, or file name to use by default. + */ + defaultPath?: string; + /** + * Custom label for the confirmation button, when left empty the default label will + * be used. + */ + buttonLabel?: string; + filters?: FileFilter[]; + /** + * Message to display above text fields. + * + * @platform darwin + */ + message?: string; + /** + * Custom label for the text displayed in front of the filename text field. + * + * @platform darwin + */ + nameFieldLabel?: string; + /** + * Show the tags input box, defaults to `true`. + * + * @platform darwin + */ + showsTagField?: boolean; + /** + * Create a security scoped bookmark when packaged for the Mac App Store. If this + * option is enabled and the file doesn't already exist a blank file will be + * created at the chosen path. + * + * @platform darwin,mas + */ + securityScopedBookmarks?: boolean; +} + +export interface OpenDialogOptions { + title?: string; + defaultPath?: string; + /** + * Custom label for the confirmation button, when left empty the default label will + * be used. + */ + buttonLabel?: string; + filters?: FileFilter[]; + /** + * Contains which features the dialog should use. The following values are + * supported: + */ + properties?: Array<'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory'>; + /** + * Message to display above input boxes. + * + * @platform darwin + */ + message?: string; + /** + * Create security scoped bookmarks when packaged for the Mac App Store. + * + * @platform darwin,mas + */ + securityScopedBookmarks?: boolean; +} + +export interface OpenDialogReturnValue { + /** + * whether or not the dialog was canceled. + */ + canceled: boolean; + /** + * An array of file paths chosen by the user. If the dialog is cancelled this will + * be an empty array. + */ + filePaths: string[]; + /** + * An array matching the `filePaths` array of base64 encoded strings which contains + * security scoped bookmark data. `securityScopedBookmarks` must be enabled for + * this to be populated. (For return values, see table here.) + * + * @platform darwin,mas + */ + bookmarks?: string[]; +} + +export interface SaveDialogReturnValue { + /** + * whether or not the dialog was canceled. + */ + canceled: boolean; + /** + * If the dialog is canceled, this will be `undefined`. + */ + filePath?: string; + /** + * Base64 encoded string which contains the security scoped bookmark data for the + * saved file. `securityScopedBookmarks` must be enabled for this to be present. + * (For return values, see table here.) + * + * @platform darwin,mas + */ + bookmark?: string; +} + +export interface CrashReporterStartOptions { + companyName: string; + /** + * URL that crash reports will be sent to as POST. + */ + submitURL: string; + /** + * Defaults to `app.name`. + */ + productName?: string; + /** + * Whether crash reports should be sent to the server. Default is `true`. + */ + uploadToServer?: boolean; + /** + * Default is `false`. + */ + ignoreSystemCrashHandler?: boolean; + /** + * An object you can define that will be sent along with the report. Only string + * properties are sent correctly. Nested objects are not supported. When using + * Windows, the property names and values must be fewer than 64 characters. + */ + extra?: Record; + /** + * Directory to store the crash reports temporarily (only used when the crash + * reporter is started via `process.crashReporter.start`). + */ + crashesDirectory?: string; +} + +export interface FileFilter { + + // Docs: http://electronjs.org/docs/api/structures/file-filter + + extensions: string[]; + name: string; +} diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js new file mode 100644 index 00000000000..1cb22cfcdd8 --- /dev/null +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -0,0 +1,115 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// @ts-check +(function () { + 'use strict'; + + const { ipcRenderer, webFrame, crashReporter } = require('electron'); + + // @ts-ignore + window.vscode = { + + /** + * A minimal set of methods exposed from ipcRenderer + * to support communication to electron-main + * + * @type {typeof import('../electron-sandbox/globals').ipcRenderer} + */ + ipcRenderer: { + + /** + * @param {string} channel + * @param {any[]} args + */ + send(channel, ...args) { + validateIPC(channel); + + ipcRenderer.send(channel, ...args); + }, + + /** + * @param {string} channel + * @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener + */ + on(channel, listener) { + validateIPC(channel); + + ipcRenderer.on(channel, listener); + }, + + /** + * @param {string} channel + * @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener + */ + once(channel, listener) { + validateIPC(channel); + + ipcRenderer.once(channel, listener); + }, + + /** + * @param {string} channel + * @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener + */ + removeListener(channel, listener) { + validateIPC(channel); + + ipcRenderer.removeListener(channel, listener); + } + }, + + /** + * Support for methods of webFrame type. + * + * @type {typeof import('../electron-sandbox/globals').webFrame} + */ + webFrame: { + + getZoomFactor() { + return webFrame.getZoomFactor(); + }, + + getZoomLevel() { + return webFrame.getZoomLevel(); + }, + + /** + * @param {number} level + */ + setZoomLevel(level) { + webFrame.setZoomLevel(level); + } + }, + + /** + * Support for methods of crashReporter type. + * + * @type {typeof import('../electron-sandbox/globals').crashReporter} + */ + crashReporter: { + + /** + * @param {Electron.CrashReporterStartOptions} options + */ + start(options) { + crashReporter.start(options); + } + } + }; + + //#region Utilities + + /** + * @param {string} channel + */ + function validateIPC(channel) { + if (!channel || !channel.startsWith('vscode:')) { + throw new Error(`Unsupported event IPC channel '${channel}'`); + } + } + + //#endregion +}()); diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts new file mode 100644 index 00000000000..0cd04e036d4 --- /dev/null +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -0,0 +1,93 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { CrashReporterStartOptions } from 'vs/base/parts/sandbox/common/electronTypes'; + +export const ipcRenderer = (window as any).vscode.ipcRenderer as { + + /** + * Listens to `channel`, when a new message arrives `listener` would be called with + * `listener(event, args...)`. + */ + on(channel: string, listener: (event: unknown, ...args: any[]) => void): void; + + /** + * Adds a one time `listener` function for the event. This `listener` is invoked + * only the next time a message is sent to `channel`, after which it is removed. + */ + once(channel: string, listener: (event: unknown, ...args: any[]) => void): void; + + /** + * Removes the specified `listener` from the listener array for the specified + * `channel`. + */ + removeListener(channel: string, listener: (event: unknown, ...args: any[]) => void): void; + + /** + * Send an asynchronous message to the main process via `channel`, along with + * arguments. Arguments will be serialized with the Structured Clone Algorithm, + * just like `postMessage`, so prototype chains will not be included. Sending + * Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception. + * + * > **NOTE**: Sending non-standard JavaScript types such as DOM objects or special + * Electron objects is deprecated, and will begin throwing an exception starting + * with Electron 9. + * + * The main process handles it by listening for `channel` with the `ipcMain` + * module. + */ + send(channel: string, ...args: any[]): void; +}; + +export const webFrame = (window as any).vscode.webFrame as { + + /** + * The current zoom factor. + */ + getZoomFactor(): number; + + /** + * The current zoom level. + */ + getZoomLevel(): number; + + /** + * Changes the zoom level to the specified level. The original size is 0 and each + * increment above or below represents zooming 20% larger or smaller to default + * limits of 300% and 50% of original size, respectively. + */ + setZoomLevel(level: number): void; +}; + +export const crashReporter = (window as any).vscode.crashReporter as { + + /** + * You are required to call this method before using any other `crashReporter` APIs + * and in each process (main/renderer) from which you want to collect crash + * reports. You can pass different options to `crashReporter.start` when calling + * from different processes. + * + * **Note** Child processes created via the `child_process` module will not have + * access to the Electron modules. Therefore, to collect crash reports from them, + * use `process.crashReporter.start` instead. Pass the same options as above along + * with an additional one called `crashesDirectory` that should point to a + * directory to store the crash reports temporarily. You can test this out by + * calling `process.crash()` to crash the child process. + * + * **Note:** If you need send additional/updated `extra` parameters after your + * first call `start` you can call `addExtraParameter` on macOS or call `start` + * again with the new/updated `extra` parameters on Linux and Windows. + * + * **Note:** On macOS and windows, Electron uses a new `crashpad` client for crash + * collection and reporting. If you want to enable crash reporting, initializing + * `crashpad` from the main process using `crashReporter.start` is required + * regardless of which process you want to collect crashes from. Once initialized + * this way, the crashpad handler collects crashes from all processes. You still + * have to call `crashReporter.start` from the renderer or child process, otherwise + * crashes from them will get reported without `companyName`, `productName` or any + * of the `extra` information. + */ + start(options: CrashReporterStartOptions): void; +}; diff --git a/src/vs/platform/dialogs/node/dialogs.ts b/src/vs/base/parts/sandbox/test/electron-sandbox/globals.test.ts similarity index 56% rename from src/vs/platform/dialogs/node/dialogs.ts rename to src/vs/base/parts/sandbox/test/electron-sandbox/globals.test.ts index 754693da712..ac3e6511710 100644 --- a/src/vs/platform/dialogs/node/dialogs.ts +++ b/src/vs/base/parts/sandbox/test/electron-sandbox/globals.test.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; +import * as assert from 'assert'; +import { ipcRenderer, crashReporter, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; -export interface INativeOpenDialogOptions { - forceNewWindow?: boolean; - - defaultPath?: string; - - telemetryEventName?: string; - telemetryExtraData?: ITelemetryData; -} +suite('Sandbox', () => { + test('globals', () => { + assert.ok(ipcRenderer); + assert.ok(crashReporter); + assert.ok(webFrame); + }); +}); diff --git a/src/vs/base/test/common/extpath.test.ts b/src/vs/base/test/common/extpath.test.ts index 02aa3a96377..0760e2c8b91 100644 --- a/src/vs/base/test/common/extpath.test.ts +++ b/src/vs/base/test/common/extpath.test.ts @@ -130,4 +130,41 @@ suite('Paths', () => { assert.equal(extpath.indexOfPath('/some/long/path', '/some/long', false), 0); assert.equal(extpath.indexOfPath('/some/long/path', '/PATH', true), 10); }); + + test('parseLineAndColumnAware', () => { + let res = extpath.parseLineAndColumnAware('/foo/bar'); + assert.equal(res.path, '/foo/bar'); + assert.equal(res.line, undefined); + assert.equal(res.column, undefined); + + res = extpath.parseLineAndColumnAware('/foo/bar:33'); + assert.equal(res.path, '/foo/bar'); + assert.equal(res.line, 33); + assert.equal(res.column, 1); + + res = extpath.parseLineAndColumnAware('/foo/bar:33:34'); + assert.equal(res.path, '/foo/bar'); + assert.equal(res.line, 33); + assert.equal(res.column, 34); + + res = extpath.parseLineAndColumnAware('C:\\foo\\bar'); + assert.equal(res.path, 'C:\\foo\\bar'); + assert.equal(res.line, undefined); + assert.equal(res.column, undefined); + + res = extpath.parseLineAndColumnAware('C:\\foo\\bar:33'); + assert.equal(res.path, 'C:\\foo\\bar'); + assert.equal(res.line, 33); + assert.equal(res.column, 1); + + res = extpath.parseLineAndColumnAware('C:\\foo\\bar:33:34'); + assert.equal(res.path, 'C:\\foo\\bar'); + assert.equal(res.line, 33); + assert.equal(res.column, 34); + + res = extpath.parseLineAndColumnAware('/foo/bar:abb'); + assert.equal(res.path, '/foo/bar:abb'); + assert.equal(res.line, undefined); + assert.equal(res.column, undefined); + }); }); diff --git a/src/vs/code/electron-browser/issue/issueReporterMain.ts b/src/vs/code/electron-browser/issue/issueReporterMain.ts index 24c2b5372ac..06797ea956c 100644 --- a/src/vs/code/electron-browser/issue/issueReporterMain.ts +++ b/src/vs/code/electron-browser/issue/issueReporterMain.ts @@ -3,10 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { clipboard, ipcRenderer, shell, webFrame } from 'electron'; +import 'vs/css!./media/issueReporter'; +import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; +import { ipcRenderer, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import * as os from 'os'; import * as browser from 'vs/base/browser/browser'; -import { $ } from 'vs/base/browser/dom'; +import { $, windowOpenNoOpener } from 'vs/base/browser/dom'; import { Button } from 'vs/base/browser/ui/button/button'; import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; @@ -15,21 +17,19 @@ import { debounce } from 'vs/base/common/decorators'; import { Disposable } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import { escape } from 'vs/base/common/strings'; -import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; -import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; +import { getDelayedChannel, createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net'; import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil'; import { IssueReporterData as IssueReporterModelData, IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel'; import BaseHtml from 'vs/code/electron-browser/issue/issueReporterPage'; -import 'vs/css!./media/issueReporter'; import { localize } from 'vs/nls'; import { isRemoteDiagnosticError, SystemInfo } from 'vs/platform/diagnostics/common/diagnostics'; import { EnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; +import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -import { ISettingsSearchIssueReporterData, IssueReporterData, IssueReporterExtensionData, IssueReporterFeatures, IssueReporterStyles, IssueType } from 'vs/platform/issue/node/issue'; +import { ISettingsSearchIssueReporterData, IssueReporterData, IssueReporterExtensionData, IssueReporterFeatures, IssueReporterStyles, IssueType } from 'vs/platform/issue/common/issue'; import { getLogLevel, ILogService } from 'vs/platform/log/common/log'; import { FollowerLogService, LoggerChannelClient } from 'vs/platform/log/common/logIpc'; import { SpdLogService } from 'vs/platform/log/node/spdlogService'; @@ -64,6 +64,7 @@ export function startup(configuration: IssueReporterConfiguration) { export class IssueReporter extends Disposable { private environmentService!: INativeEnvironmentService; + private electronService!: IElectronService; private telemetryService!: ITelemetryService; private logService!: ILogService; private readonly issueReporterModel: IssueReporterModel; @@ -324,6 +325,9 @@ export class IssueReporter extends Disposable { const mainProcessService = new MainProcessService(configuration.windowId); serviceCollection.set(IMainProcessService, mainProcessService); + this.electronService = new ElectronService(configuration.windowId, mainProcessService) as IElectronService; + serviceCollection.set(IElectronService, this.electronService); + this.environmentService = new EnvironmentService(configuration, configuration.execPath); const logService = new SpdLogService(`issuereporter${configuration.windowId}`, this.environmentService.logsPath, getLogLevel(this.environmentService)); @@ -462,7 +466,7 @@ export class IssueReporter extends Disposable { this.addEventListener('extensionBugsLink', 'click', (e: Event) => { const url = (e.target).innerText; - shell.openExternal(url); + windowOpenNoOpener(url); }); this.addEventListener('disableExtensions', 'keydown', (e: Event) => { @@ -941,9 +945,9 @@ export class IssueReporter extends Disposable { private async writeToClipboard(baseUrl: string, issueBody: string): Promise { return new Promise((resolve, reject) => { - ipcRenderer.once('vscode:issueReporterClipboardResponse', (_: unknown, shouldWrite: boolean) => { + ipcRenderer.once('vscode:issueReporterClipboardResponse', async (event: unknown, shouldWrite: boolean) => { if (shouldWrite) { - clipboard.writeText(issueBody); + await this.electronService.writeClipboardText(issueBody); resolve(baseUrl + `&body=${encodeURIComponent(localize('pasteData', "We have written the needed data into your clipboard because it was too large to send. Please paste."))}`); } else { reject(); @@ -1194,7 +1198,7 @@ export class IssueReporter extends Disposable { event.stopPropagation(); // Exclude right click if (event.which < 3) { - shell.openExternal((event.target).href); + windowOpenNoOpener((event.target).href); this.telemetryService.publicLog2('issueReporterViewSimilarIssue'); } } diff --git a/src/vs/code/electron-browser/issue/issueReporterModel.ts b/src/vs/code/electron-browser/issue/issueReporterModel.ts index 96bae9110ee..47059817368 100644 --- a/src/vs/code/electron-browser/issue/issueReporterModel.ts +++ b/src/vs/code/electron-browser/issue/issueReporterModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { assign } from 'vs/base/common/objects'; -import { IssueType, ISettingSearchResult, IssueReporterExtensionData } from 'vs/platform/issue/node/issue'; +import { IssueType, ISettingSearchResult, IssueReporterExtensionData } from 'vs/platform/issue/common/issue'; import { SystemInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; export interface IssueReporterData { diff --git a/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts index 2dda07e6fed..e7ce5b7e463 100644 --- a/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts +++ b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { IssueReporterModel } from 'vs/code/electron-browser/issue/issueReporterModel'; import { normalizeGitHubUrl } from 'vs/platform/issue/common/issueReporterUtil'; -import { IssueType } from 'vs/platform/issue/node/issue'; +import { IssueType } from 'vs/platform/issue/common/issue'; suite('IssueReporter', () => { diff --git a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts index 9684cbd4c20..250f09adab6 100644 --- a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts +++ b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts @@ -4,16 +4,17 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/processExplorer'; -import { webFrame, ipcRenderer, clipboard } from 'electron'; +import { clipboard } from 'electron'; +import { webFrame, ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { repeat } from 'vs/base/common/strings'; import { totalmem } from 'os'; import product from 'vs/platform/product/common/product'; import { localize } from 'vs/nls'; -import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/node/issue'; +import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue'; import * as browser from 'vs/base/browser/browser'; import * as platform from 'vs/base/common/platform'; import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu'; -import { popup } from 'vs/base/parts/contextmenu/electron-browser/contextmenu'; +import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu'; import { ProcessItem } from 'vs/base/common/processes'; import { addDisposableListener } from 'vs/base/browser/dom'; import { DisposableStore } from 'vs/base/common/lifecycle'; @@ -369,7 +370,7 @@ function requestProcessList(totalWaitTime: number): void { // Wait at least a second between requests. if (waited > 1000) { - ipcRenderer.send('windowsInfoRequest'); + ipcRenderer.send('vscode:windowsInfoRequest'); ipcRenderer.send('vscode:listProcesses'); } else { requestProcessList(waited); @@ -393,18 +394,18 @@ export function startup(data: ProcessExplorerData): void { createCloseListener(); // Map window process pids to titles, annotate process names with this when rendering to distinguish between them - ipcRenderer.on('vscode:windowsInfoResponse', (_event: unknown, windows: any[]) => { + ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => { mapPidToWindowTitle = new Map(); windows.forEach(window => mapPidToWindowTitle.set(window.pid, window.title)); }); - ipcRenderer.on('vscode:listProcessesResponse', (_event: Event, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => { + ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => { updateProcessInfo(processRoots); requestProcessList(0); }); lastRequestTime = Date.now(); - ipcRenderer.send('windowsInfoRequest'); + ipcRenderer.send('vscode:windowsInfoRequest'); ipcRenderer.send('vscode:listProcesses'); document.onkeydown = (e: KeyboardEvent) => { diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index d317071db46..850ae498d0c 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -27,7 +27,7 @@ import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProper import { TelemetryAppenderChannel } from 'vs/platform/telemetry/node/telemetryIpc'; import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService'; import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; -import { ipcRenderer } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { ILogService, LogLevel, ILoggerService } from 'vs/platform/log/common/log'; import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; @@ -35,26 +35,25 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza import { combinedDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { DownloadService } from 'vs/platform/download/common/downloadService'; import { IDownloadService } from 'vs/platform/download/common/download'; -import { IChannel, IServerChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; -import { createChannelSender, createChannelReceiver } from 'vs/base/parts/ipc/node/ipc'; +import { IChannel, IServerChannel, StaticRouter, createChannelSender, createChannelReceiver } from 'vs/base/parts/ipc/common/ipc'; import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner'; import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner'; import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner'; import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { SpdLogService } from 'vs/platform/log/node/spdlogService'; import { DiagnosticsService, IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService'; import { DiagnosticsChannel } from 'vs/platform/diagnostics/node/diagnosticsIpc'; import { FileService } from 'vs/platform/files/common/fileService'; import { IFileService } from 'vs/platform/files/common/files'; -import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider'; +import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { Schemas } from 'vs/base/common/network'; import { IProductService } from 'vs/platform/product/common/productService'; import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync'; import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService'; import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService'; import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncChannel, StorageKeysSyncRegistryChannelClient, UserDataSyncMachinesServiceChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { LoggerService } from 'vs/platform/log/node/loggerService'; import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; @@ -66,7 +65,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; import { UserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSyncEnablementService'; import { IAuthenticationTokenService, AuthenticationTokenService } from 'vs/platform/authentication/common/authentication'; -import { AuthenticationTokenServiceChannel } from 'vs/platform/authentication/common/authenticationIpc'; +import { AuthenticationTokenServiceChannel } from 'vs/platform/authentication/electron-browser/authenticationIpc'; import { UserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSyncBackupStoreService'; import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { ExtensionTipsService } from 'vs/platform/extensionManagement/node/extensionTipsService'; @@ -90,7 +89,11 @@ interface ISharedProcessInitData { const eventPrefix = 'monacoworkbench'; class MainProcessService implements IMainProcessService { - constructor(private server: Server, private mainRouter: StaticRouter) { } + + constructor( + private server: Server, + private mainRouter: StaticRouter + ) { } _serviceBrand: undefined; @@ -110,7 +113,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat const onExit = () => disposables.dispose(); process.once('exit', onExit); - ipcRenderer.once('electron-main->shared-process: exit', onExit); + ipcRenderer.once('vscode:electron-main->shared-process=exit', onExit); disposables.add(server); @@ -298,17 +301,17 @@ async function handshake(configuration: ISharedProcessConfiguration): Promise(c => { - ipcRenderer.once('electron-main->shared-process: payload', (_: any, r: ISharedProcessInitData) => c(r)); + ipcRenderer.once('vscode:electron-main->shared-process=payload', (event: unknown, r: ISharedProcessInitData) => c(r)); // tell electron-main we are ready to receive payload - ipcRenderer.send('shared-process->electron-main: ready-for-payload'); + ipcRenderer.send('vscode:shared-process->electron-main=ready-for-payload'); }); // await IPC connection and signal this back to electron-main const server = await setupIPC(data.sharedIPCHandle); - ipcRenderer.send('shared-process->electron-main: ipc-ready'); + ipcRenderer.send('vscode:shared-process->electron-main=ipc-ready'); // await initialization and signal this back to electron-main await main(server, data, configuration); - ipcRenderer.send('shared-process->electron-main: init-done'); + ipcRenderer.send('vscode:shared-process->electron-main=init-done'); } diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 25300327917..4d8f90aa2ba 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -8,7 +8,6 @@ import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/plat import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService'; import { IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext } from 'vs/platform/windows/node/window'; -import { ActiveWindowManager } from 'vs/code/node/activeWindowTracker'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { getShellEnvironment } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; @@ -32,12 +31,12 @@ import { NullTelemetryService, combinedAppender, LogAppender } from 'vs/platform import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc'; import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService'; import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; -import { getDelayedChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc'; -import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipc'; +import { getDelayedChannel, StaticRouter, createChannelReceiver } from 'vs/base/parts/ipc/common/ipc'; import product from 'vs/platform/product/common/product'; import { ProxyAuthHandler } from 'vs/code/electron-main/auth'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; +import { ActiveWindowManager } from 'vs/platform/windows/electron-main/windowTracker'; import { URI } from 'vs/base/common/uri'; import { hasWorkspaceFileExtension, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { WorkspacesService } from 'vs/platform/workspaces/electron-main/workspacesService'; @@ -45,14 +44,12 @@ import { getMachineId } from 'vs/base/node/id'; import { Win32UpdateService } from 'vs/platform/update/electron-main/updateService.win32'; import { LinuxUpdateService } from 'vs/platform/update/electron-main/updateService.linux'; import { DarwinUpdateService } from 'vs/platform/update/electron-main/updateService.darwin'; -import { IIssueService } from 'vs/platform/issue/node/issue'; -import { IssueMainService } from 'vs/platform/issue/electron-main/issueMainService'; +import { IssueMainService, IIssueMainService } from 'vs/platform/issue/electron-main/issueMainService'; import { LoggerChannel } from 'vs/platform/log/common/logIpc'; import { setUnexpectedErrorHandler, onUnexpectedError } from 'vs/base/common/errors'; import { ElectronURLListener } from 'vs/platform/url/electron-main/electronUrlListener'; import { serve as serveDriver } from 'vs/platform/driver/electron-main/driver'; -import { IMenubarService } from 'vs/platform/menubar/node/menubar'; -import { MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService'; +import { IMenubarMainService, MenubarMainService } from 'vs/platform/menubar/electron-main/menubarMainService'; import { RunOnceScheduler } from 'vs/base/common/async'; import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu'; import { homedir } from 'os'; @@ -65,7 +62,7 @@ import { GlobalStorageDatabaseChannel } from 'vs/platform/storage/node/storageIp import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService'; import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; import { WorkspacesHistoryMainService, IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; -import { URLService } from 'vs/platform/url/node/urlService'; +import { NativeURLService } from 'vs/platform/url/common/urlService'; import { WorkspacesMainService, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { statSync } from 'fs'; import { DiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsIpc'; @@ -472,10 +469,10 @@ export class CodeApplication extends Disposable { const diagnosticsChannel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('diagnostics'))); services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService, [diagnosticsChannel])); - services.set(IIssueService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv])); + services.set(IIssueMainService, new SyncDescriptor(IssueMainService, [machineId, this.userEnv])); services.set(IElectronMainService, new SyncDescriptor(ElectronMainService)); services.set(IWorkspacesService, new SyncDescriptor(WorkspacesService)); - services.set(IMenubarService, new SyncDescriptor(MenubarMainService)); + services.set(IMenubarMainService, new SyncDescriptor(MenubarMainService)); const storageMainService = new StorageMainService(this.logService, this.environmentService); services.set(IStorageMainService, storageMainService); @@ -485,7 +482,7 @@ export class CodeApplication extends Disposable { services.set(IBackupMainService, backupMainService); services.set(IWorkspacesHistoryMainService, new SyncDescriptor(WorkspacesHistoryMainService)); - services.set(IURLService, new SyncDescriptor(URLService)); + services.set(IURLService, new SyncDescriptor(NativeURLService)); services.set(IWorkspacesMainService, new SyncDescriptor(WorkspacesMainService)); // Telemetry @@ -556,8 +553,8 @@ export class CodeApplication extends Disposable { const updateChannel = new UpdateChannel(updateService); electronIpcServer.registerChannel('update', updateChannel); - const issueService = accessor.get(IIssueService); - const issueChannel = createChannelReceiver(issueService); + const issueMainService = accessor.get(IIssueMainService); + const issueChannel = createChannelReceiver(issueMainService); electronIpcServer.registerChannel('issue', issueChannel); const electronMainService = accessor.get(IElectronMainService); @@ -573,8 +570,8 @@ export class CodeApplication extends Disposable { const workspacesChannel = createChannelReceiver(workspacesService); electronIpcServer.registerChannel('workspaces', workspacesChannel); - const menubarService = accessor.get(IMenubarService); - const menubarChannel = createChannelReceiver(menubarService); + const menubarMainService = accessor.get(IMenubarMainService); + const menubarChannel = createChannelReceiver(menubarMainService); electronIpcServer.registerChannel('menubar', menubarChannel); const urlService = accessor.get(IURLService); diff --git a/src/vs/code/electron-main/auth.ts b/src/vs/code/electron-main/auth.ts index 5e09e170c84..b74e1c4e9c1 100644 --- a/src/vs/code/electron-main/auth.ts +++ b/src/vs/code/electron-main/auth.ts @@ -59,8 +59,7 @@ export class ProxyAuthHandler extends Disposable { title: 'VS Code', webPreferences: { nodeIntegration: true, - webviewTag: true, - enableWebSQL: false + webviewTag: true } }; diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 650d665d2ca..744bfea9530 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -13,7 +13,7 @@ import { mkdirp } from 'vs/base/node/pfs'; import { validatePaths } from 'vs/code/node/paths'; import { LifecycleMainService, ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net'; -import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; diff --git a/src/vs/code/electron-main/sharedProcess.ts b/src/vs/code/electron-main/sharedProcess.ts index f44b3d08713..e9f95448a08 100644 --- a/src/vs/code/electron-main/sharedProcess.ts +++ b/src/vs/code/electron-main/sharedProcess.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { URI } from 'vs/base/common/uri'; import { memoize } from 'vs/base/common/decorators'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { BrowserWindow, ipcMain, WebContents, Event as ElectronEvent } from 'electron'; @@ -32,7 +33,7 @@ export class SharedProcess implements ISharedProcess { @IThemeMainService private readonly themeMainService: IThemeMainService ) { // overall ready promise when shared process signals initialization is done - this._whenReady = new Promise(c => ipcMain.once('shared-process->electron-main: init-done', () => c(undefined))); + this._whenReady = new Promise(c => ipcMain.once('vscode:shared-process->electron-main=init-done', () => c(undefined))); } @memoize @@ -41,10 +42,10 @@ export class SharedProcess implements ISharedProcess { show: false, backgroundColor: this.themeMainService.getBackgroundColor(), webPreferences: { + preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath, images: false, nodeIntegration: true, webgl: false, - enableWebSQL: false, disableBlinkFeatures: 'Auxclick' // do NOT change, allows us to identify this window as shared-process in the process explorer } }); @@ -105,18 +106,18 @@ export class SharedProcess implements ISharedProcess { return new Promise(c => { // send payload once shared process is ready to receive it - disposables.add(Event.once(Event.fromNodeEventEmitter(ipcMain, 'shared-process->electron-main: ready-for-payload', ({ sender }: { sender: WebContents }) => sender))(sender => { - sender.send('electron-main->shared-process: payload', { + disposables.add(Event.once(Event.fromNodeEventEmitter(ipcMain, 'vscode:shared-process->electron-main=ready-for-payload', ({ sender }: { sender: WebContents }) => sender))(sender => { + sender.send('vscode:electron-main->shared-process=payload', { sharedIPCHandle: this.environmentService.sharedIPCHandle, args: this.environmentService.args, logLevel: this.logService.getLevel() }); // signal exit to shared process when we get disposed - disposables.add(toDisposable(() => sender.send('electron-main->shared-process: exit'))); + disposables.add(toDisposable(() => sender.send('vscode:electron-main->shared-process=exit'))); // complete IPC-ready promise when shared process signals this to us - ipcMain.once('shared-process->electron-main: ipc-ready', () => c(undefined)); + ipcMain.once('vscode:shared-process->electron-main=ipc-ready', () => c(undefined)); })); }); } diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 98a37e53ae7..193fa596db1 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -163,10 +163,10 @@ export class CodeWindow extends Disposable implements ICodeWindow { show: !isFullscreenOrMaximized, title: product.nameLong, webPreferences: { + preload: URI.parse(this.doGetPreloadUrl()).fsPath, nodeIntegration: true, nodeIntegrationInWorker: RUN_TEXTMATE_IN_WORKER, - webviewTag: true, - enableWebSQL: false + webviewTag: true } }; @@ -777,6 +777,10 @@ export class CodeWindow extends Disposable implements ICodeWindow { return `${require.toUrl('vs/code/electron-browser/workbench/workbench.html')}?config=${encodeURIComponent(JSON.stringify(config))}`; } + private doGetPreloadUrl(): string { + return require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js'); + } + serializeWindowState(): IWindowState { if (!this._win) { return defaultWindowState(); diff --git a/src/vs/code/node/paths.ts b/src/vs/code/node/paths.ts index 24c2529c587..b2912383c3c 100644 --- a/src/vs/code/node/paths.ts +++ b/src/vs/code/node/paths.ts @@ -33,9 +33,9 @@ function doValidatePaths(args: string[], gotoLineMode?: boolean): string[] { const result = args.map(arg => { let pathCandidate = String(arg); - let parsedPath: IPathWithLineAndColumn | undefined = undefined; + let parsedPath: extpath.IPathWithLineAndColumn | undefined = undefined; if (gotoLineMode) { - parsedPath = parseLineAndColumnAware(pathCandidate); + parsedPath = extpath.parseLineAndColumnAware(pathCandidate); pathCandidate = parsedPath.path; } @@ -87,42 +87,7 @@ function preparePath(cwd: string, p: string): string { return p; } -export interface IPathWithLineAndColumn { - path: string; - line?: number; - column?: number; -} - -export function parseLineAndColumnAware(rawPath: string): IPathWithLineAndColumn { - const segments = rawPath.split(':'); // C:\file.txt:: - - let path: string | null = null; - let line: number | null = null; - let column: number | null = null; - - segments.forEach(segment => { - const segmentAsNumber = Number(segment); - if (!types.isNumber(segmentAsNumber)) { - path = !!path ? [path, segment].join(':') : segment; // a colon can well be part of a path (e.g. C:\...) - } else if (line === null) { - line = segmentAsNumber; - } else if (column === null) { - column = segmentAsNumber; - } - }); - - if (!path) { - throw new Error('Format for `--goto` should be: `FILE:LINE(:COLUMN)`'); - } - - return { - path: path, - line: line !== null ? line : undefined, - column: column !== null ? column : line !== null ? 1 : undefined // if we have a line, make sure column is also set - }; -} - -function toPath(p: IPathWithLineAndColumn): string { +function toPath(p: extpath.IPathWithLineAndColumn): string { const segments = [p.path]; if (types.isNumber(p.line)) { diff --git a/src/vs/editor/common/model/editStack.ts b/src/vs/editor/common/model/editStack.ts index 24c38f88141..8fc15ea71a0 100644 --- a/src/vs/editor/common/model/editStack.ts +++ b/src/vs/editor/common/model/editStack.ts @@ -12,6 +12,7 @@ import { IUndoRedoService, IResourceUndoRedoElement, UndoRedoElementType, IWorks import { URI } from 'vs/base/common/uri'; import { TextChange, compressConsecutiveTextChanges } from 'vs/editor/common/model/textChange'; import * as buffer from 'vs/base/common/buffer'; +import { IDisposable } from 'vs/base/common/lifecycle'; function uriGetComparisonKey(resource: URI): string { return resource.toString(); @@ -138,6 +139,10 @@ class SingleModelEditStackData { } } +export interface IUndoRedoDelegate { + prepareUndoRedo(element: MultiModelEditStackElement): Promise | IDisposable | void; +} + export class SingleModelEditStackElement implements IResourceUndoRedoElement { public model: ITextModel | URI; @@ -224,6 +229,8 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement { private readonly _editStackElementsArr: SingleModelEditStackElement[]; private readonly _editStackElementsMap: Map; + private _delegate: IUndoRedoDelegate | null; + public get resources(): readonly URI[] { return this._editStackElementsArr.map(editStackElement => editStackElement.resource); } @@ -240,6 +247,27 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement { const key = uriGetComparisonKey(editStackElement.resource); this._editStackElementsMap.set(key, editStackElement); } + this._delegate = null; + } + + public setDelegate(delegate: IUndoRedoDelegate): void { + this._delegate = delegate; + } + + public prepareUndoRedo(): Promise | IDisposable | void { + if (this._delegate) { + return this._delegate.prepareUndoRedo(this); + } + } + + public getMissingModels(): URI[] { + const result: URI[] = []; + for (const editStackElement of this._editStackElementsArr) { + if (URI.isUri(editStackElement.model)) { + result.push(editStackElement.model); + } + } + return result; } public setModel(model: ITextModel | URI): void { diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 9ab05132790..eab07c9ad48 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -113,12 +113,12 @@ interface IRawConfig { const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? DefaultEndOfLine.LF : DefaultEndOfLine.CRLF; -interface EditStackPastFutureElements { +export interface EditStackPastFutureElements { past: EditStackElement[]; future: EditStackElement[]; } -function isEditStackPastFutureElements(undoElements: IPastFutureElements): undoElements is EditStackPastFutureElements { +export function isEditStackPastFutureElements(undoElements: IPastFutureElements): undoElements is EditStackPastFutureElements { return (isEditStackElements(undoElements.past) && isEditStackElements(undoElements.future)); } diff --git a/src/vs/editor/common/services/modelUndoRedoParticipant.ts b/src/vs/editor/common/services/modelUndoRedoParticipant.ts new file mode 100644 index 00000000000..0862ccf8d6e --- /dev/null +++ b/src/vs/editor/common/services/modelUndoRedoParticipant.ts @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IModelService } from 'vs/editor/common/services/modelService'; +import { ITextModelService } from 'vs/editor/common/services/resolverService'; +import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo'; +import { isEditStackPastFutureElements } from 'vs/editor/common/services/modelServiceImpl'; +import { IUndoRedoDelegate, MultiModelEditStackElement } from 'vs/editor/common/model/editStack'; + +export class ModelUndoRedoParticipant extends Disposable implements IUndoRedoDelegate { + constructor( + @IModelService private readonly _modelService: IModelService, + @ITextModelService private readonly _textModelService: ITextModelService, + @IUndoRedoService private readonly _undoRedoService: IUndoRedoService, + ) { + super(); + this._register(this._modelService.onModelRemoved((model) => { + // a model will get disposed, so let's check if the undo redo stack is maintained + const elements = this._undoRedoService.getElements(model.uri); + if (elements.past.length === 0 && elements.future.length === 0) { + return; + } + if (!isEditStackPastFutureElements(elements)) { + return; + } + for (const element of elements.past) { + if (element.type === UndoRedoElementType.Workspace) { + element.setDelegate(this); + } + } + for (const element of elements.future) { + if (element.type === UndoRedoElementType.Workspace) { + element.setDelegate(this); + } + } + })); + } + + public prepareUndoRedo(element: MultiModelEditStackElement): IDisposable | Promise { + // Load all the needed text models + const missingModels = element.getMissingModels(); + if (missingModels.length === 0) { + // All models are available! + return Disposable.None; + } + + const disposablesPromises = missingModels.map(async (uri) => { + try { + const reference = await this._textModelService.createModelReference(uri); + return reference; + } catch (err) { + // This model could not be loaded, maybe it was deleted in the meantime? + return Disposable.None; + } + }); + + return Promise.all(disposablesPromises).then(disposables => { + return { + dispose: () => dispose(disposables) + }; + }); + } +} diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index b22036d6b2f..8d2f6668924 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -359,7 +359,7 @@ export class CommonFindController extends Disposable implements IEditorContribut && this._editor.hasModel() && !this._editor.getModel().isTooLargeForSyncing() ) { - return this._clipboardService.readFindText(); + return this._clipboardService.readFindTextSync(); } return ''; } @@ -370,7 +370,7 @@ export class CommonFindController extends Disposable implements IEditorContribut && this._editor.hasModel() && !this._editor.getModel().isTooLargeForSyncing() ) { - this._clipboardService.writeFindText(text); + this._clipboardService.writeFindTextSync(text); } } } diff --git a/src/vs/editor/contrib/rename/rename.ts b/src/vs/editor/contrib/rename/rename.ts index 865d05eccdf..ec9fa64d5cc 100644 --- a/src/vs/editor/contrib/rename/rename.ts +++ b/src/vs/editor/contrib/rename/rename.ts @@ -28,7 +28,6 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { IdleValue, raceCancellation } from 'vs/base/common/async'; -import { withNullAsUndefined } from 'vs/base/common/types'; import { ILogService } from 'vs/platform/log/common/log'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -38,6 +37,7 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/tex class RenameSkeleton { private readonly _providers: RenameProvider[]; + private _providerRenameIdx: number = 0; constructor( private readonly model: ITextModel, @@ -51,30 +51,45 @@ class RenameSkeleton { } async resolveRenameLocation(token: CancellationToken): Promise { - const firstProvider = this._providers[0]; - if (!firstProvider) { - return undefined; - } - let res: RenameLocation & Rejection | undefined; - if (firstProvider.resolveRenameLocation) { - res = withNullAsUndefined(await firstProvider.resolveRenameLocation(this.model, this.position, token)); - } + const rejects: string[] = []; - if (!res) { - const word = this.model.getWordAtPosition(this.position); - if (word) { - return { - range: new Range(this.position.lineNumber, word.startColumn, this.position.lineNumber, word.endColumn), - text: word.word - }; + for (this._providerRenameIdx = 0; this._providerRenameIdx < this._providers.length; this._providerRenameIdx++) { + const provider = this._providers[this._providerRenameIdx]; + if (!provider.resolveRenameLocation) { + break; } + let res = await provider.resolveRenameLocation(this.model, this.position, token); + if (!res) { + continue; + } + if (res.rejectReason) { + rejects.push(res.rejectReason); + continue; + } + return res; } - return res; + const word = this.model.getWordAtPosition(this.position); + if (!word) { + return { + range: Range.fromPositions(this.position), + text: '', + rejectReason: rejects.length > 0 ? rejects.join('\n') : undefined + }; + } + return { + range: new Range(this.position.lineNumber, word.startColumn, this.position.lineNumber, word.endColumn), + text: word.word, + rejectReason: rejects.length > 0 ? rejects.join('\n') : undefined + }; } - async provideRenameEdits(newName: string, i: number, rejects: string[], token: CancellationToken): Promise { + async provideRenameEdits(newName: string, token: CancellationToken): Promise { + return this._provideRenameEdits(newName, this._providerRenameIdx, [], token); + } + + private async _provideRenameEdits(newName: string, i: number, rejects: string[], token: CancellationToken): Promise { const provider = this._providers[i]; if (!provider) { return { @@ -85,16 +100,21 @@ class RenameSkeleton { const result = await provider.provideRenameEdits(this.model, this.position, newName, token); if (!result) { - return this.provideRenameEdits(newName, i + 1, rejects.concat(nls.localize('no result', "No result.")), token); + return this._provideRenameEdits(newName, i + 1, rejects.concat(nls.localize('no result', "No result.")), token); } else if (result.rejectReason) { - return this.provideRenameEdits(newName, i + 1, rejects.concat(result.rejectReason), token); + return this._provideRenameEdits(newName, i + 1, rejects.concat(result.rejectReason), token); } return result; } } export async function rename(model: ITextModel, position: Position, newName: string): Promise { - return new RenameSkeleton(model, position).provideRenameEdits(newName, 0, [], CancellationToken.None); + const skeleton = new RenameSkeleton(model, position); + const loc = await skeleton.resolveRenameLocation(CancellationToken.None); + if (loc?.rejectReason) { + return { edits: [], rejectReason: loc.rejectReason }; + } + return skeleton.provideRenameEdits(newName, CancellationToken.None); } // --- register actions and commands @@ -194,7 +214,7 @@ class RenameController implements IEditorContribution { this.editor.focus(); - const renameOperation = raceCancellation(skeleton.provideRenameEdits(inputFieldResult.newName, 0, [], this._cts.token), this._cts.token).then(async renameResult => { + const renameOperation = raceCancellation(skeleton.provideRenameEdits(inputFieldResult.newName, this._cts.token), this._cts.token).then(async renameResult => { if (!renameResult || !this.editor.hasModel()) { return; diff --git a/src/vs/editor/contrib/rename/renameInputField.ts b/src/vs/editor/contrib/rename/renameInputField.ts index d527c20ea96..2be443c8c55 100644 --- a/src/vs/editor/contrib/rename/renameInputField.ts +++ b/src/vs/editor/contrib/rename/renameInputField.ts @@ -82,7 +82,7 @@ export class RenameInputField implements IContentWidget { const updateLabel = () => { const [accept, preview] = this._acceptKeybindings; this._keybindingService.lookupKeybinding(accept); - this._label!.innerText = localize('label', "{0} to Rename, {1} to Preview", this._keybindingService.lookupKeybinding(accept)?.getLabel(), this._keybindingService.lookupKeybinding(preview)?.getLabel()); + this._label!.innerText = localize({ key: 'label', comment: ['placeholders are keybindings, e.g "F2 to Rename, Shift+F2 to Preview"'] }, "{0} to Rename, {1} to Preview", this._keybindingService.lookupKeybinding(accept)?.getLabel(), this._keybindingService.lookupKeybinding(preview)?.getLabel()); }; updateLabel(); this._disposables.add(this._keybindingService.onDidUpdateKeybindings(updateLabel)); diff --git a/src/vs/editor/standalone/browser/simpleServices.ts b/src/vs/editor/standalone/browser/simpleServices.ts index 999ddcde452..c5a48fbeff3 100644 --- a/src/vs/editor/standalone/browser/simpleServices.ts +++ b/src/vs/editor/standalone/browser/simpleServices.ts @@ -108,12 +108,11 @@ function withTypedEditor(widget: IEditor, codeEditorCallback: (editor: ICodeE export class SimpleEditorModelResolverService implements ITextModelService { public _serviceBrand: undefined; - private readonly modelService: IModelService | undefined; private editor?: IEditor; - constructor(modelService: IModelService | undefined) { - this.modelService = modelService; - } + constructor( + @IModelService private readonly modelService: IModelService + ) { } public setEditor(editor: IEditor): void { this.editor = editor; @@ -146,7 +145,7 @@ export class SimpleEditorModelResolverService implements ITextModelService { } private findModel(editor: ICodeEditor, resource: URI): ITextModel | null { - let model = this.modelService ? this.modelService.getModel(resource) : editor.getModel(); + let model = this.modelService.getModel(resource); if (model && model.uri.toString() !== resource.toString()) { return null; } diff --git a/src/vs/platform/authentication/common/authenticationIpc.ts b/src/vs/platform/authentication/electron-browser/authenticationIpc.ts similarity index 99% rename from src/vs/platform/authentication/common/authenticationIpc.ts rename to src/vs/platform/authentication/electron-browser/authenticationIpc.ts index e9f74ac9659..2b9411b9465 100644 --- a/src/vs/platform/authentication/common/authenticationIpc.ts +++ b/src/vs/platform/authentication/electron-browser/authenticationIpc.ts @@ -7,7 +7,6 @@ import { IServerChannel } from 'vs/base/parts/ipc/common/ipc'; import { Event } from 'vs/base/common/event'; import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication'; - export class AuthenticationTokenServiceChannel implements IServerChannel { constructor(private readonly service: IAuthenticationTokenService) { } diff --git a/src/vs/platform/clipboard/browser/clipboardService.ts b/src/vs/platform/clipboard/browser/clipboardService.ts index 8cbddd37004..85855d06dd8 100644 --- a/src/vs/platform/clipboard/browser/clipboardService.ts +++ b/src/vs/platform/clipboard/browser/clipboardService.ts @@ -11,11 +11,15 @@ export class BrowserClipboardService implements IClipboardService { _serviceBrand: undefined; - private _internalResourcesClipboard: URI[] | undefined; + private readonly mapTextToType = new Map(); // unsupported in web (only in-memory) async writeText(text: string, type?: string): Promise { + + // With type: only in-memory is supported if (type) { - return; // TODO@sbatten support for writing a specific type into clipboard is unsupported + this.mapTextToType.set(type, text); + + return; } // Guard access to navigator.clipboard with try/catch @@ -52,8 +56,10 @@ export class BrowserClipboardService implements IClipboardService { } async readText(type?: string): Promise { + + // With type: only in-memory is supported if (type) { - return ''; // TODO@sbatten support for reading a specific type from clipboard is unsupported + return this.mapTextToType.get(type) || ''; } // Guard access to navigator.clipboard with try/catch @@ -68,26 +74,42 @@ export class BrowserClipboardService implements IClipboardService { } } + private findText = ''; // unsupported in web (only in-memory) + + async readFindText(): Promise { + return this.findText; + } + + async writeFindText(text: string): Promise { + this.findText = text; + } + + private resources: URI[] = []; // unsupported in web (only in-memory) + + async writeResources(resources: URI[]): Promise { + this.resources = resources; + } + + async readResources(): Promise { + return this.resources; + } + + async hasResources(): Promise { + return this.resources.length > 0; + } + + /** @deprecated */ readTextSync(): string | undefined { return undefined; } - readFindText(): string { - // @ts-expect-error - return undefined; + /** @deprecated */ + readFindTextSync(): string { + return this.findText; } - writeFindText(text: string): void { } - - writeResources(resources: URI[]): void { - this._internalResourcesClipboard = resources; - } - - readResources(): URI[] { - return this._internalResourcesClipboard || []; - } - - hasResources(): boolean { - return this._internalResourcesClipboard !== undefined && this._internalResourcesClipboard.length > 0; + /** @deprecated */ + writeFindTextSync(text: string): void { + this.findText = text; } } diff --git a/src/vs/platform/clipboard/common/clipboardService.ts b/src/vs/platform/clipboard/common/clipboardService.ts index 11bf563393a..73cc53f0ae2 100644 --- a/src/vs/platform/clipboard/common/clipboardService.ts +++ b/src/vs/platform/clipboard/common/clipboardService.ts @@ -22,30 +22,38 @@ export interface IClipboardService { */ readText(type?: string): Promise; - readTextSync(): string | undefined; - /** * Reads text from the system find pasteboard. */ - readFindText(): string; + readFindText(): Promise; /** * Writes text to the system find pasteboard. */ - writeFindText(text: string): void; + writeFindText(text: string): Promise; /** * Writes resources to the system clipboard. */ - writeResources(resources: URI[]): void; + writeResources(resources: URI[]): Promise; /** * Reads resources from the system clipboard. */ - readResources(): URI[]; + readResources(): Promise; /** * Find out if resources are copied to the clipboard. */ - hasResources(): boolean; + hasResources(): Promise; + + + /** @deprecated */ + readTextSync(): string | undefined; + + /** @deprecated */ + readFindTextSync(): string; + + /** @deprecated */ + writeFindTextSync(text: string): void; } diff --git a/src/vs/platform/dialogs/common/dialogs.ts b/src/vs/platform/dialogs/common/dialogs.ts index ece49da3e7c..50ef02af982 100644 --- a/src/vs/platform/dialogs/common/dialogs.ts +++ b/src/vs/platform/dialogs/common/dialogs.ts @@ -272,3 +272,12 @@ export function getFileNamesMessage(fileNamesOrResources: readonly (string | URI message.push(''); return message.join('\n'); } + +export interface INativeOpenDialogOptions { + forceNewWindow?: boolean; + + defaultPath?: string; + + telemetryEventName?: string; + telemetryExtraData?: ITelemetryData; +} diff --git a/src/vs/platform/dialogs/electron-main/dialogs.ts b/src/vs/platform/dialogs/electron-main/dialogs.ts index c694c003e9b..8f1b34aead4 100644 --- a/src/vs/platform/dialogs/electron-main/dialogs.ts +++ b/src/vs/platform/dialogs/electron-main/dialogs.ts @@ -11,7 +11,7 @@ import { isMacintosh } from 'vs/base/common/platform'; import { dirname } from 'vs/base/common/path'; import { normalizeNFC } from 'vs/base/common/normalization'; import { exists } from 'vs/base/node/pfs'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { withNullAsUndefined } from 'vs/base/common/types'; import { localize } from 'vs/nls'; import { WORKSPACE_FILTER } from 'vs/platform/workspaces/common/workspaces'; diff --git a/src/vs/platform/driver/electron-browser/driver.ts b/src/vs/platform/driver/electron-browser/driver.ts index 2594eef1361..9e39b4d6eb0 100644 --- a/src/vs/platform/driver/electron-browser/driver.ts +++ b/src/vs/platform/driver/electron-browser/driver.ts @@ -6,11 +6,11 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { WindowDriverChannel, WindowDriverRegistryChannelClient } from 'vs/platform/driver/node/driver'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; -import * as electron from 'electron'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { remote } from 'electron'; import { timeout } from 'vs/base/common/async'; import { BaseWindowDriver } from 'vs/platform/driver/browser/baseDriver'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; class WindowDriver extends BaseWindowDriver { @@ -32,7 +32,7 @@ class WindowDriver extends BaseWindowDriver { private async _click(selector: string, clickCount: number, offset?: { x: number, y: number }): Promise { const { x, y } = await this._getElementXY(selector, offset); - const webContents: electron.WebContents = (electron as any).remote.getCurrentWebContents(); + const webContents = remote.getCurrentWebContents(); webContents.sendInputEvent({ type: 'mouseDown', x, y, button: 'left', clickCount } as any); await timeout(10); diff --git a/src/vs/platform/electron/node/electron.ts b/src/vs/platform/electron/common/electron.ts similarity index 75% rename from src/vs/platform/electron/node/electron.ts rename to src/vs/platform/electron/common/electron.ts index 43203239b81..506bfb5af27 100644 --- a/src/vs/platform/electron/node/electron.ts +++ b/src/vs/platform/electron/common/electron.ts @@ -4,19 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; -import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'electron'; -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; +import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'vs/base/parts/sandbox/common/electronTypes'; +import { IOpenedWindow, IWindowOpenable, IOpenEmptyWindowOptions, INativeOpenWindowOptions } from 'vs/platform/windows/common/windows'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; -import { INativeOpenWindowOptions, IOpenedWindow } from 'vs/platform/windows/node/window'; -export const IElectronService = createDecorator('electronService'); - -export interface IElectronService { +export interface ICommonElectronService { _serviceBrand: undefined; + // Properties + readonly windowId: number; + // Events readonly onWindowOpen: Event; @@ -61,6 +60,16 @@ export interface IElectronService { setDocumentEdited(edited: boolean): Promise; openExternal(url: string): Promise; updateTouchBar(items: ISerializableCommandAction[][]): Promise; + moveItemToTrash(fullPath: string, deleteOnFail?: boolean): Promise; + + // clipboard + readClipboardText(type?: 'selection' | 'clipboard'): Promise; + writeClipboardText(text: string, type?: 'selection' | 'clipboard'): Promise; + readClipboardFindText(): Promise; + writeClipboardFindText(text: string): Promise; + writeClipboardBuffer(format: string, buffer: Uint8Array, type?: 'selection' | 'clipboard'): Promise; + readClipboardBuffer(format: string): Promise; + hasClipboard(format: string, type?: 'selection' | 'clipboard'): Promise; // macOS Touchbar newWindowTab(): Promise; diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index c21fb966278..6772a1f6783 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -5,13 +5,13 @@ import { Event } from 'vs/base/common/event'; import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows'; -import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron'; -import { INativeOpenWindowOptions, IOpenedWindow, OpenContext } from 'vs/platform/windows/node/window'; +import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app, clipboard } from 'electron'; +import { OpenContext } from 'vs/platform/windows/node/window'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; -import { IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; +import { IOpenedWindow, INativeOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { isMacintosh } from 'vs/base/common/platform'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { ICommonElectronService } from 'vs/platform/electron/common/electron'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { AddFirstParameterToFunctions } from 'vs/base/common/types'; @@ -23,9 +23,9 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation' import { ILogService } from 'vs/platform/log/common/log'; import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService'; -export interface IElectronMainService extends AddFirstParameterToFunctions /* only methods, not events */, number | undefined /* window ID */> { } +export interface IElectronMainService extends AddFirstParameterToFunctions /* only methods, not events */, number | undefined /* window ID */> { } -export const IElectronMainService = createDecorator('electronMainService'); +export const IElectronMainService = createDecorator('electronMainService'); export class ElectronMainService implements IElectronMainService { @@ -41,6 +41,12 @@ export class ElectronMainService implements IElectronMainService { ) { } + //#region Properties + + get windowId(): never { throw new Error('Not implemented in electron-main'); } + + //#endregion + //#region Events readonly onWindowOpen: Event = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-created', (_, window: BrowserWindow) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId)); @@ -293,6 +299,43 @@ export class ElectronMainService implements IElectronMainService { } } + async moveItemToTrash(windowId: number | undefined, fullPath: string): Promise { + return shell.moveItemToTrash(fullPath); + } + + //#endregion + + + //#region clipboard + + async readClipboardText(windowId: number | undefined, type?: 'selection' | 'clipboard'): Promise { + return clipboard.readText(type); + } + + async writeClipboardText(windowId: number | undefined, text: string, type?: 'selection' | 'clipboard'): Promise { + return clipboard.writeText(text, type); + } + + async readClipboardFindText(windowId: number | undefined,): Promise { + return clipboard.readFindText(); + } + + async writeClipboardFindText(windowId: number | undefined, text: string): Promise { + return clipboard.writeFindText(text); + } + + async writeClipboardBuffer(windowId: number | undefined, format: string, buffer: Uint8Array, type?: 'selection' | 'clipboard'): Promise { + return clipboard.writeBuffer(format, buffer as Buffer, type); + } + + async readClipboardBuffer(windowId: number | undefined, format: string): Promise { + return clipboard.readBuffer(format); + } + + async hasClipboard(windowId: number | undefined, format: string, type?: 'selection' | 'clipboard'): Promise { + return clipboard.has(format, type); + } + //#endregion //#region macOS Touchbar diff --git a/src/vs/platform/electron/electron-sandbox/electron.ts b/src/vs/platform/electron/electron-sandbox/electron.ts new file mode 100644 index 00000000000..aa17d948100 --- /dev/null +++ b/src/vs/platform/electron/electron-sandbox/electron.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ICommonElectronService } from 'vs/platform/electron/common/electron'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; + +export const IElectronService = createDecorator('electronService'); + +export interface IElectronService extends ICommonElectronService { } + +export class ElectronService { + + _serviceBrand: undefined; + + constructor( + readonly windowId: number, + @IMainProcessService mainProcessService: IMainProcessService + ) { + return createChannelSender(mainProcessService.getChannel('electron'), { + context: windowId, + properties: (() => { + const properties = new Map(); + properties.set('windowId', windowId); + + return properties; + })() + }); + } +} diff --git a/src/vs/platform/environment/node/argvHelper.ts b/src/vs/platform/environment/node/argvHelper.ts index 11e54c68b8a..eda11907549 100644 --- a/src/vs/platform/environment/node/argvHelper.ts +++ b/src/vs/platform/environment/node/argvHelper.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { firstIndex } from 'vs/base/common/arrays'; import { localize } from 'vs/nls'; -import { MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/node/files'; +import { MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files'; import { parseArgs, ErrorReporter, OPTIONS, ParsedArgs } from 'vs/platform/environment/node/argv'; function parseAndValidate(cmdLineArgs: string[], reportWarnings: boolean): ParsedArgs { diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 25c274ca05f..2df5bfb9329 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -362,10 +362,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService { } const { id, uuid } = extension ? extension.identifier : arg1; let query = new Query() - .withFlags(Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated) + .withFlags(Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties) .withPage(1, 1) - .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code') - .withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished)); + .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code'); if (uuid) { query = query.withFilter(FilterType.ExtensionId, uuid); @@ -426,8 +425,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { let query = new Query() .withFlags(Flags.IncludeLatestVersionOnly, Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties) .withPage(1, pageSize) - .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code') - .withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished)); + .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code'); if (text) { // Use category filter instead of "category:themes" @@ -484,6 +482,11 @@ export class ExtensionGalleryService implements IExtensionGalleryService { } private queryGallery(query: Query, token: CancellationToken): Promise<{ galleryExtensions: IRawGalleryExtension[], total: number; }> { + // Always exclude non validated and unpublished extensions + query = query + .withFlags(query.flags, Flags.ExcludeNonValidated) + .withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished)); + if (!this.isEnabled()) { return Promise.reject(new Error('No extension gallery service configured.')); } @@ -602,10 +605,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService { getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise { let query = new Query() - .withFlags(Flags.IncludeVersions, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated) + .withFlags(Flags.IncludeVersions, Flags.IncludeFiles, Flags.IncludeVersionProperties) .withPage(1, 1) - .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code') - .withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished)); + .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code'); if (extension.identifier.uuid) { query = query.withFilter(FilterType.ExtensionId, extension.identifier.uuid); diff --git a/src/vs/platform/files/common/files.ts b/src/vs/platform/files/common/files.ts index 7438ec84efe..058deff7c26 100644 --- a/src/vs/platform/files/common/files.ts +++ b/src/vs/platform/files/common/files.ts @@ -824,7 +824,6 @@ export function etag(stat: { mtime: number | undefined, size: number | undefined return stat.mtime.toString(29) + stat.size.toString(31); } - export function whenProviderRegistered(file: URI, fileService: IFileService): Promise { if (fileService.canHandleResource(URI.from({ scheme: file.scheme }))) { return Promise.resolve(); @@ -838,3 +837,9 @@ export function whenProviderRegistered(file: URI, fileService: IFileService): Pr }); }); } + +/** + * Desktop only: limits for memory sizes + */ +export const MIN_MAX_MEMORY_SIZE_MB = 2048; +export const FALLBACK_MAX_MEMORY_SIZE_MB = 4096; diff --git a/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts b/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts index 2c23af873f1..de3211dae17 100644 --- a/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts +++ b/src/vs/platform/files/electron-browser/diskFileSystemProvider.ts @@ -3,15 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { shell } from 'electron'; -import { DiskFileSystemProvider as NodeDiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; +import { DiskFileSystemProvider as NodeDiskFileSystemProvider, IDiskFileSystemProviderOptions } from 'vs/platform/files/node/diskFileSystemProvider'; import { FileDeleteOptions, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { isWindows } from 'vs/base/common/platform'; import { localize } from 'vs/nls'; import { basename } from 'vs/base/common/path'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; export class DiskFileSystemProvider extends NodeDiskFileSystemProvider { + constructor( + logService: ILogService, + private electronService: IElectronService, + options?: IDiskFileSystemProviderOptions + ) { + super(logService, options); + } + get capabilities(): FileSystemProviderCapabilities { if (!this._capabilities) { this._capabilities = super.capabilities | FileSystemProviderCapabilities.Trash; @@ -25,9 +34,9 @@ export class DiskFileSystemProvider extends NodeDiskFileSystemProvider { return super.doDelete(filePath, opts); } - const result = shell.moveItemToTrash(filePath); + const result = await this.electronService.moveItemToTrash(filePath); if (!result) { throw new Error(isWindows ? localize('binFailed', "Failed to move '{0}' to the recycle bin", basename(filePath)) : localize('trashFailed', "Failed to move '{0}' to the trash", basename(filePath))); } } -} \ No newline at end of file +} diff --git a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts index 803ff185ab9..33579429f5e 100644 --- a/src/vs/platform/files/test/electron-browser/diskFileService.test.ts +++ b/src/vs/platform/files/test/electron-browser/diskFileService.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { tmpdir } from 'os'; import { FileService } from 'vs/platform/files/common/fileService'; import { Schemas } from 'vs/base/common/network'; -import { DiskFileSystemProvider } from 'vs/platform/files/electron-browser/diskFileSystemProvider'; +import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { generateUuid } from 'vs/base/common/uuid'; import { join, basename, dirname, posix } from 'vs/base/common/path'; diff --git a/src/vs/platform/ipc/electron-browser/mainProcessService.ts b/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts similarity index 94% rename from src/vs/platform/ipc/electron-browser/mainProcessService.ts rename to src/vs/platform/ipc/electron-sandbox/mainProcessService.ts index c72b1c703d3..b8ffa053a08 100644 --- a/src/vs/platform/ipc/electron-browser/mainProcessService.ts +++ b/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; -import { Client } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser'; +import { Client } from 'vs/base/parts/ipc/electron-sandbox/ipc.electron-sandbox'; import { Disposable } from 'vs/base/common/lifecycle'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const IMainProcessService = createDecorator('mainProcessService'); diff --git a/src/vs/platform/issue/node/issue.ts b/src/vs/platform/issue/common/issue.ts similarity index 93% rename from src/vs/platform/issue/node/issue.ts rename to src/vs/platform/issue/common/issue.ts index 08a9c5d456f..17d3fe40830 100644 --- a/src/vs/platform/issue/node/issue.ts +++ b/src/vs/platform/issue/common/issue.ts @@ -3,10 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; - -export const IIssueService = createDecorator('issueService'); - // Since data sent through the service is serialized to JSON, functions will be lost, so Color objects // should not be sent as their 'toString' method will be stripped. Instead convert to strings before sending. export interface WindowStyles { @@ -91,7 +87,7 @@ export interface ProcessExplorerData extends WindowData { styles: ProcessExplorerStyles; } -export interface IIssueService { +export interface ICommonIssueService { _serviceBrand: undefined; openReporter(data: IssueReporterData): Promise; openProcessExplorer(data: ProcessExplorerData): Promise; diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts index 90e20854239..81a5be1fe4b 100644 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ b/src/vs/platform/issue/electron-main/issueMainService.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import * as objects from 'vs/base/common/objects'; import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; -import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/node/issue'; +import { ICommonIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue'; import { BrowserWindow, ipcMain, screen, IpcMainEvent, Display, shell } from 'electron'; import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; import { PerformanceInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; @@ -18,10 +18,16 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IWindowState } from 'vs/platform/windows/electron-main/windows'; import { listProcesses } from 'vs/base/node/ps'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; +import { URI } from 'vs/base/common/uri'; +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; const DEFAULT_BACKGROUND_COLOR = '#1E1E1E'; -export class IssueMainService implements IIssueService { +export const IIssueMainService = createDecorator('issueMainService'); + +export interface IIssueMainService extends ICommonIssueService { } + +export class IssueMainService implements ICommonIssueService { _serviceBrand: undefined; _issueWindow: BrowserWindow | null = null; _issueParentWindow: BrowserWindow | null = null; @@ -163,12 +169,11 @@ export class IssueMainService implements IIssueService { } }); - ipcMain.on('windowsInfoRequest', (event: IpcMainEvent) => { + ipcMain.on('vscode:windowsInfoRequest', (event: IpcMainEvent) => { this.launchMainService.getMainProcessInfo().then(info => { event.sender.send('vscode:windowsInfoResponse', info.windows); }); }); - } openReporter(data: IssueReporterData): Promise { @@ -189,8 +194,8 @@ export class IssueMainService implements IIssueService { title: localize('issueReporter', "Issue Reporter"), backgroundColor: data.styles.backgroundColor || DEFAULT_BACKGROUND_COLOR, webPreferences: { - nodeIntegration: true, - enableWebSQL: false + preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath, + nodeIntegration: true } }); @@ -225,7 +230,7 @@ export class IssueMainService implements IIssueService { if (!this._processExplorerWindow) { this._processExplorerParentWindow = BrowserWindow.getFocusedWindow(); if (this._processExplorerParentWindow) { - const position = this.getWindowPosition(this._processExplorerParentWindow, 800, 300); + const position = this.getWindowPosition(this._processExplorerParentWindow, 800, 500); this._processExplorerWindow = new BrowserWindow({ skipTaskbar: true, resizable: true, @@ -239,8 +244,8 @@ export class IssueMainService implements IIssueService { backgroundColor: data.styles.backgroundColor, title: localize('processExplorer', "Process Explorer"), webPreferences: { - nodeIntegration: true, - enableWebSQL: false + preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath, + nodeIntegration: true } }); diff --git a/src/vs/platform/issue/electron-sandbox/issue.ts b/src/vs/platform/issue/electron-sandbox/issue.ts new file mode 100644 index 00000000000..4e84d42806e --- /dev/null +++ b/src/vs/platform/issue/electron-sandbox/issue.ts @@ -0,0 +1,11 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ICommonIssueService } from 'vs/platform/issue/common/issue'; + +export const IIssueService = createDecorator('issueService'); + +export interface IIssueService extends ICommonIssueService { } diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index f81f8534749..235c3a7e78c 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -124,6 +124,7 @@ export const keyboardNavigationSettingKey = 'workbench.list.keyboardNavigation'; export const automaticKeyboardNavigationSettingKey = 'workbench.list.automaticKeyboardNavigation'; const treeIndentKey = 'workbench.tree.indent'; const treeRenderIndentGuidesKey = 'workbench.tree.renderIndentGuides'; +const listSmoothScrolling = 'workbench.list.smoothScrolling'; function getHorizontalScrollingSetting(configurationService: IConfigurationService): boolean { return getMigratedSettingValue(configurationService, horizontalScrollingKey, 'workbench.tree.horizontalScrolling'); @@ -823,6 +824,7 @@ function workbenchTreeDataPreamble(treeIndentKey), renderIndentGuides: configurationService.getValue(treeRenderIndentGuidesKey), + smoothScrolling: configurationService.getValue(listSmoothScrolling), automaticKeyboardNavigation: getAutomaticKeyboardNavigation(), simpleKeyboardNavigation: keyboardNavigation === 'simple', filterOnType: keyboardNavigation === 'filter', @@ -898,25 +900,33 @@ class WorkbenchTreeInternals { this.hasSelectionOrFocus.set(selection.length > 0 || focus.length > 0); }), configurationService.onDidChangeConfiguration(e => { + let options: any = {}; if (e.affectsConfiguration(openModeSettingKey)) { - tree.updateOptions({ openOnSingleClick: useSingleClickToOpen(configurationService) }); + options = { ...options, openOnSingleClick: useSingleClickToOpen(configurationService) }; } if (e.affectsConfiguration(multiSelectModifierSettingKey)) { this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService); } if (e.affectsConfiguration(treeIndentKey)) { const indent = configurationService.getValue(treeIndentKey); - tree.updateOptions({ indent }); + options = { ...options, indent }; } if (e.affectsConfiguration(treeRenderIndentGuidesKey)) { const renderIndentGuides = configurationService.getValue(treeRenderIndentGuidesKey); - tree.updateOptions({ renderIndentGuides }); + options = { ...options, renderIndentGuides }; + } + if (e.affectsConfiguration(listSmoothScrolling)) { + const smoothScrolling = configurationService.getValue(listSmoothScrolling); + options = { ...options, smoothScrolling }; } if (e.affectsConfiguration(keyboardNavigationSettingKey)) { updateKeyboardNavigation(); } if (e.affectsConfiguration(automaticKeyboardNavigationSettingKey)) { - tree.updateOptions({ automaticKeyboardNavigation: getAutomaticKeyboardNavigation() }); + options = { ...options, automaticKeyboardNavigation: getAutomaticKeyboardNavigation() }; + } + if (Object.keys(options).length > 0) { + tree.updateOptions(options); } }), this.contextKeyService.onDidChangeContext(e => { @@ -1001,6 +1011,11 @@ configurationRegistry.registerConfiguration({ default: 'onHover', description: localize('render tree indent guides', "Controls whether the tree should render indent guides.") }, + [listSmoothScrolling]: { + type: 'boolean', + default: false, + description: localize('list smoothScrolling setting', "Controls whether lists and trees have smooth scrolling."), + }, [keyboardNavigationSettingKey]: { 'type': 'string', 'enum': ['simple', 'highlight', 'filter'], diff --git a/src/vs/platform/menubar/node/menubar.ts b/src/vs/platform/menubar/common/menubar.ts similarity index 90% rename from src/vs/platform/menubar/node/menubar.ts rename to src/vs/platform/menubar/common/menubar.ts index db246d1b487..69b74dfbe33 100644 --- a/src/vs/platform/menubar/node/menubar.ts +++ b/src/vs/platform/menubar/common/menubar.ts @@ -3,14 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; -export const IMenubarService = createDecorator('menubarService'); - -export interface IMenubarService { - _serviceBrand: undefined; - +export interface ICommonMenubarService { updateMenubar(windowId: number, menuData: IMenubarData): Promise; } diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index ac66913edbf..46e88cd5537 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -18,7 +18,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { mnemonicMenuLabel as baseMnemonicLabel } from 'vs/base/common/labels'; import { IWindowsMainService, IWindowsCountChangedEvent } from 'vs/platform/windows/electron-main/windows'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; -import { IMenubarData, IMenubarKeybinding, MenubarMenuItem, isMenubarMenuItemSeparator, isMenubarMenuItemSubmenu, isMenubarMenuItemAction, IMenubarMenu, isMenubarMenuItemUriAction } from 'vs/platform/menubar/node/menubar'; +import { IMenubarData, IMenubarKeybinding, MenubarMenuItem, isMenubarMenuItemSeparator, isMenubarMenuItemSubmenu, isMenubarMenuItemAction, IMenubarMenu, isMenubarMenuItemUriAction } from 'vs/platform/menubar/common/menubar'; import { URI } from 'vs/base/common/uri'; import { IStateService } from 'vs/platform/state/node/state'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; diff --git a/src/vs/platform/menubar/electron-main/menubarMainService.ts b/src/vs/platform/menubar/electron-main/menubarMainService.ts index 7cadd57ecdb..243bc205d7b 100644 --- a/src/vs/platform/menubar/electron-main/menubarMainService.ts +++ b/src/vs/platform/menubar/electron-main/menubarMainService.ts @@ -3,13 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IMenubarService, IMenubarData } from 'vs/platform/menubar/node/menubar'; +import { ICommonMenubarService, IMenubarData } from 'vs/platform/menubar/common/menubar'; import { Menubar } from 'vs/platform/menubar/electron-main/menubar'; import { ILogService } from 'vs/platform/log/common/log'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; -export class MenubarMainService implements IMenubarService { +export const IMenubarMainService = createDecorator('menubarMainService'); + +export interface IMenubarMainService extends ICommonMenubarService { + _serviceBrand: undefined; +} + +export class MenubarMainService implements IMenubarMainService { _serviceBrand: undefined; diff --git a/src/vs/platform/menubar/electron-sandbox/menubar.ts b/src/vs/platform/menubar/electron-sandbox/menubar.ts new file mode 100644 index 00000000000..51ef554c932 --- /dev/null +++ b/src/vs/platform/menubar/electron-sandbox/menubar.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ICommonMenubarService } from 'vs/platform/menubar/common/menubar'; + +export const IMenubarService = createDecorator('menubarService'); + +export interface IMenubarService extends ICommonMenubarService { + _serviceBrand: undefined; +} diff --git a/src/vs/platform/undoRedo/common/undoRedo.ts b/src/vs/platform/undoRedo/common/undoRedo.ts index 935e3ffcb22..3dc62c71af2 100644 --- a/src/vs/platform/undoRedo/common/undoRedo.ts +++ b/src/vs/platform/undoRedo/common/undoRedo.ts @@ -5,6 +5,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; +import { IDisposable } from 'vs/base/common/lifecycle'; export const IUndoRedoService = createDecorator('undoRedoService'); @@ -28,6 +29,13 @@ export interface IWorkspaceUndoRedoElement { undo(): Promise | void; redo(): Promise | void; split(): IResourceUndoRedoElement[]; + + /** + * If implemented, will be invoked before calling `undo()` or `redo()`. + * This is a good place to prepare everything such that the calls to `undo()` or `redo()` are synchronous. + * If a disposable is returned, it will be invoked to clean things up. + */ + prepareUndoRedo?(): Promise | IDisposable | void; } export type IUndoRedoElement = IResourceUndoRedoElement | IWorkspaceUndoRedoElement; diff --git a/src/vs/platform/undoRedo/common/undoRedoService.ts b/src/vs/platform/undoRedo/common/undoRedoService.ts index 9858c9eb6af..16e1921703a 100644 --- a/src/vs/platform/undoRedo/common/undoRedoService.ts +++ b/src/vs/platform/undoRedo/common/undoRedoService.ts @@ -12,6 +12,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import Severity from 'vs/base/common/severity'; import { Schemas } from 'vs/base/common/network'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; function uriGetComparisonKey(resource: URI): string { return resource.toString(); @@ -76,7 +77,7 @@ class RemovedResources { let messages: string[] = []; if (externalRemoval.length > 0) { - messages.push(nls.localize('externalRemoval', "The following files have been closed: {0}.", externalRemoval.join(', '))); + messages.push(nls.localize('externalRemoval', "The following files have been closed and modified on disk: {0}.", externalRemoval.join(', '))); } if (noParallelUniverses.length > 0) { messages.push(nls.localize('noParallelUniverses', "The following files have been modified in an incompatible way: {0}.", noParallelUniverses.join(', '))); @@ -151,14 +152,147 @@ class WorkspaceStackElement { type StackElement = ResourceStackElement | WorkspaceStackElement; class ResourceEditStack { - public resource: URI; - public past: StackElement[]; - public future: StackElement[]; + public readonly resource: URI; + private readonly strResource: string; + private _past: StackElement[]; + private _future: StackElement[]; + public locked: boolean; - constructor(resource: URI) { + constructor(resource: URI, strResource: string) { this.resource = resource; - this.past = []; - this.future = []; + this.strResource = strResource; + this._past = []; + this._future = []; + this.locked = false; + } + + public dispose(): void { + for (const element of this._past) { + if (element.type === UndoRedoElementType.Workspace) { + element.removeResource(this.resource, this.strResource, RemovedResourceReason.ExternalRemoval); + } + } + for (const element of this._future) { + if (element.type === UndoRedoElementType.Workspace) { + element.removeResource(this.resource, this.strResource, RemovedResourceReason.ExternalRemoval); + } + } + } + + public flushAllElements(): void { + this._past = []; + this._future = []; + } + + public setElementsIsValid(isValid: boolean): void { + for (const element of this._past) { + if (element.type === UndoRedoElementType.Workspace) { + element.setValid(this.resource, this.strResource, isValid); + } else { + element.setValid(isValid); + } + } + for (const element of this._future) { + if (element.type === UndoRedoElementType.Workspace) { + element.setValid(this.resource, this.strResource, isValid); + } else { + element.setValid(isValid); + } + } + } + + public pushElement(element: StackElement): void { + // remove the future + for (const futureElement of this._future) { + if (futureElement.type === UndoRedoElementType.Workspace) { + futureElement.removeResource(this.resource, this.strResource, RemovedResourceReason.NoParallelUniverses); + } + } + this._future = []; + if (this._past.length > 0) { + const lastElement = this._past[this._past.length - 1]; + if (lastElement.type === UndoRedoElementType.Resource && !lastElement.isValid) { + // clear undo stack + this._past = []; + } + } + this._past.push(element); + } + + public getElements(): IPastFutureElements { + const past: IUndoRedoElement[] = []; + const future: IUndoRedoElement[] = []; + + for (const element of this._past) { + past.push(element.actual); + } + for (const element of this._future) { + future.push(element.actual); + } + + return { past, future }; + } + + public getClosestPastElement(): StackElement | null { + if (this._past.length === 0) { + return null; + } + return this._past[this._past.length - 1]; + } + + public getClosestFutureElement(): StackElement | null { + if (this._future.length === 0) { + return null; + } + return this._future[this._future.length - 1]; + } + + public hasPastElements(): boolean { + return (this._past.length > 0); + } + + public hasFutureElements(): boolean { + return (this._future.length > 0); + } + + public splitPastWorkspaceElement(toRemove: WorkspaceStackElement, individualMap: Map): void { + for (let j = this._past.length - 1; j >= 0; j--) { + if (this._past[j] === toRemove) { + if (individualMap.has(this.strResource)) { + // gets replaced + this._past[j] = individualMap.get(this.strResource)!; + } else { + // gets deleted + this._past.splice(j, 1); + } + break; + } + } + } + + public splitFutureWorkspaceElement(toRemove: WorkspaceStackElement, individualMap: Map): void { + for (let j = this._future.length - 1; j >= 0; j--) { + if (this._future[j] === toRemove) { + if (individualMap.has(this.strResource)) { + // gets replaced + this._future[j] = individualMap.get(this.strResource)!; + } else { + // gets deleted + this._future.splice(j, 1); + } + break; + } + } + } + + public moveBackward(element: StackElement): void { + this._past.pop(); + this._future.push(element); + } + + public moveForward(element: StackElement): void { + this._future.pop(); + this._past.push(element); } } @@ -184,25 +318,11 @@ export class UndoRedoService implements IUndoRedoService { if (this._editStacks.has(strResource)) { editStack = this._editStacks.get(strResource)!; } else { - editStack = new ResourceEditStack(resource); + editStack = new ResourceEditStack(resource, strResource); this._editStacks.set(strResource, editStack); } - // remove the future - for (const futureElement of editStack.future) { - if (futureElement.type === UndoRedoElementType.Workspace) { - futureElement.removeResource(resource, strResource, RemovedResourceReason.NoParallelUniverses); - } - } - editStack.future = []; - if (editStack.past.length > 0) { - const lastElement = editStack.past[editStack.past.length - 1]; - if (lastElement.type === UndoRedoElementType.Resource && !lastElement.isValid) { - // clear undo stack - editStack.past = []; - } - } - editStack.past.push(element); + editStack.pushElement(element); } } @@ -210,13 +330,11 @@ export class UndoRedoService implements IUndoRedoService { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; - if (editStack.future.length > 0) { + if (editStack.hasFutureElements()) { return null; } - if (editStack.past.length === 0) { - return null; - } - return editStack.past[editStack.past.length - 1].actual; + const closestPastElement = editStack.getClosestPastElement(); + return closestPastElement ? closestPastElement.actual : null; } return null; } @@ -234,18 +352,7 @@ export class UndoRedoService implements IUndoRedoService { continue; } const editStack = this._editStacks.get(strResource)!; - for (let j = editStack.past.length - 1; j >= 0; j--) { - if (editStack.past[j] === toRemove) { - if (individualMap.has(strResource)) { - // gets replaced - editStack.past[j] = individualMap.get(strResource)!; - } else { - // gets deleted - editStack.past.splice(j, 1); - } - break; - } - } + editStack.splitPastWorkspaceElement(toRemove, individualMap); } } @@ -262,18 +369,7 @@ export class UndoRedoService implements IUndoRedoService { continue; } const editStack = this._editStacks.get(strResource)!; - for (let j = editStack.future.length - 1; j >= 0; j--) { - if (editStack.future[j] === toRemove) { - if (individualMap.has(strResource)) { - // gets replaced - editStack.future[j] = individualMap.get(strResource)!; - } else { - // gets deleted - editStack.future.splice(j, 1); - } - break; - } - } + editStack.splitFutureWorkspaceElement(toRemove, individualMap); } } @@ -281,16 +377,7 @@ export class UndoRedoService implements IUndoRedoService { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; - for (const element of editStack.past) { - if (element.type === UndoRedoElementType.Workspace) { - element.removeResource(resource, strResource, RemovedResourceReason.ExternalRemoval); - } - } - for (const element of editStack.future) { - if (element.type === UndoRedoElementType.Workspace) { - element.removeResource(resource, strResource, RemovedResourceReason.ExternalRemoval); - } - } + editStack.dispose(); this._editStacks.delete(strResource); } } @@ -299,20 +386,7 @@ export class UndoRedoService implements IUndoRedoService { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; - for (const element of editStack.past) { - if (element.type === UndoRedoElementType.Workspace) { - element.setValid(resource, strResource, isValid); - } else { - element.setValid(isValid); - } - } - for (const element of editStack.future) { - if (element.type === UndoRedoElementType.Workspace) { - element.setValid(resource, strResource, isValid); - } else { - element.setValid(isValid); - } - } + editStack.setElementsIsValid(isValid); } } @@ -322,34 +396,25 @@ export class UndoRedoService implements IUndoRedoService { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; - return (editStack.past.length > 0 || editStack.future.length > 0); + return (editStack.hasPastElements() || editStack.hasFutureElements()); } return false; } public getElements(resource: URI): IPastFutureElements { - const past: IUndoRedoElement[] = []; - const future: IUndoRedoElement[] = []; - const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; - for (const element of editStack.past) { - past.push(element.actual); - } - for (const element of editStack.future) { - future.push(element.actual); - } + return editStack.getElements(); } - - return { past, future }; + return { past: [], future: [] }; } public canUndo(resource: URI): boolean { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; - return (editStack.past.length > 0); + return editStack.hasPastElements(); } return false; } @@ -363,55 +428,135 @@ export class UndoRedoService implements IUndoRedoService { this._notificationService.error(err); } - private _safeInvoke(element: StackElement, invoke: () => Promise | void): Promise | void { + private _acquireLocks(affectedEditStacks: ResourceEditStack[]): () => void { + // first, check if all locks can be acquired + for (const editStack of affectedEditStacks) { + if (editStack.locked) { + throw new Error('Cannot acquire edit stack lock'); + } + } + + // can acquire all locks + for (const editStack of affectedEditStacks) { + editStack.locked = true; + } + + return () => { + // release all locks + for (const editStack of affectedEditStacks) { + editStack.locked = false; + } + }; + } + + private _safeInvokeWithLocks(element: StackElement, invoke: () => Promise | void, affectedEditStacks: ResourceEditStack[], cleanup: IDisposable = Disposable.None): Promise | void { + const releaseLocks = this._acquireLocks(affectedEditStacks); + let result: Promise | void; try { result = invoke(); } catch (err) { + releaseLocks(); + cleanup.dispose(); return this._onError(err, element); } if (result) { - return result.then(undefined, (err) => this._onError(err, element)); + // result is Promise + return result.then( + () => { + releaseLocks(); + cleanup.dispose(); + }, + (err) => { + releaseLocks(); + cleanup.dispose(); + return this._onError(err, element); + } + ); + } else { + // result is void + releaseLocks(); + cleanup.dispose(); } } - private _workspaceUndo(resource: URI, element: WorkspaceStackElement): Promise | void { + private async _invokePrepare(element: WorkspaceStackElement): Promise { + if (typeof element.actual.prepareUndoRedo === 'undefined') { + return Disposable.None; + } + const result = element.actual.prepareUndoRedo(); + if (typeof result === 'undefined') { + return Disposable.None; + } + return result; + } + + private _getAffectedEditStacks(element: WorkspaceStackElement): ResourceEditStack[] { + const affectedEditStacks: ResourceEditStack[] = []; + for (const strResource of element.strResources) { + affectedEditStacks.push(this._editStacks.get(strResource)!); + } + return affectedEditStacks; + } + + private _checkWorkspaceUndo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[], checkInvalidatedResources: boolean): WorkspaceVerificationError | null { if (element.removedResources) { this._splitPastWorkspaceElement(element, element.removedResources); const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.removedResources.createMessage()); this._notificationService.info(message); - return this.undo(resource); + return new WorkspaceVerificationError(this.undo(resource)); } - if (element.invalidatedResources) { + if (checkInvalidatedResources && element.invalidatedResources) { this._splitPastWorkspaceElement(element, element.invalidatedResources); const message = nls.localize('cannotWorkspaceUndo', "Could not undo '{0}' across all files. {1}", element.label, element.invalidatedResources.createMessage()); this._notificationService.info(message); - return this.undo(resource); + return new WorkspaceVerificationError(this.undo(resource)); } // this must be the last past element in all the impacted resources! - let affectedEditStacks: ResourceEditStack[] = []; - for (const strResource of element.strResources) { - affectedEditStacks.push(this._editStacks.get(strResource)!); - } - - let cannotUndoDueToResources: URI[] = []; + const cannotUndoDueToResources: URI[] = []; for (const editStack of affectedEditStacks) { - if (editStack.past.length === 0 || editStack.past[editStack.past.length - 1] !== element) { + if (editStack.getClosestPastElement() !== element) { cannotUndoDueToResources.push(editStack.resource); } } - if (cannotUndoDueToResources.length > 0) { this._splitPastWorkspaceElement(element, null); const paths = cannotUndoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path); const message = nls.localize('cannotWorkspaceUndoDueToChanges', "Could not undo '{0}' across all files because changes were made to {1}", element.label, paths.join(', ')); this._notificationService.info(message); - return this.undo(resource); + return new WorkspaceVerificationError(this.undo(resource)); } - return this._dialogService.show( + const cannotLockDueToResources: URI[] = []; + for (const editStack of affectedEditStacks) { + if (editStack.locked) { + cannotLockDueToResources.push(editStack.resource); + } + } + if (cannotLockDueToResources.length > 0) { + this._splitPastWorkspaceElement(element, null); + const paths = cannotLockDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path); + const message = nls.localize('cannotWorkspaceUndoDueToInProgressUndoRedo', "Could not undo '{0}' across all files because there is already an undo or redo operation running on {1}", element.label, paths.join(', ')); + this._notificationService.info(message); + return new WorkspaceVerificationError(this.undo(resource)); + } + + return null; + } + + private _workspaceUndo(resource: URI, element: WorkspaceStackElement): Promise | void { + const affectedEditStacks = this._getAffectedEditStacks(element); + const verificationError = this._checkWorkspaceUndo(resource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/false); + if (verificationError) { + return verificationError.returnValue; + } + return this._confirmAndExecuteWorkspaceUndo(resource, element, affectedEditStacks); + } + + private async _confirmAndExecuteWorkspaceUndo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[]): Promise { + const result = await this._dialogService.show( Severity.Info, nls.localize('confirmWorkspace', "Would you like to undo '{0}' across all files?", element.label), [ @@ -422,33 +567,61 @@ export class UndoRedoService implements IUndoRedoService { { cancelId: 2 } - ).then((result) => { - if (result.choice === 2) { - // cancel - return; - } else if (result.choice === 0) { - for (const editStack of affectedEditStacks) { - editStack.past.pop(); - editStack.future.push(element); - } - return this._safeInvoke(element, () => element.actual.undo()); - } else { - this._splitPastWorkspaceElement(element, null); - return this.undo(resource); - } - }); + ); + + if (result.choice === 2) { + // choice: cancel + return; + } + + if (result.choice === 1) { + // choice: undo this file + this._splitPastWorkspaceElement(element, null); + return this.undo(resource); + } + + // choice: undo in all files + + // At this point, it is possible that the element has been made invalid in the meantime (due to the confirmation await) + const verificationError1 = this._checkWorkspaceUndo(resource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/false); + if (verificationError1) { + return verificationError1.returnValue; + } + + // prepare + let cleanup: IDisposable; + try { + cleanup = await this._invokePrepare(element); + } catch (err) { + return this._onError(err, element); + } + + // At this point, it is possible that the element has been made invalid in the meantime (due to the prepare await) + const verificationError2 = this._checkWorkspaceUndo(resource, element, affectedEditStacks, /*now also check that there are no more invalidated resources*/true); + if (verificationError2) { + cleanup.dispose(); + return verificationError2.returnValue; + } + + for (const editStack of affectedEditStacks) { + editStack.moveBackward(element); + } + return this._safeInvokeWithLocks(element, () => element.actual.undo(), affectedEditStacks, cleanup); } private _resourceUndo(editStack: ResourceEditStack, element: ResourceStackElement): Promise | void { if (!element.isValid) { // invalid element => immediately flush edit stack! - editStack.past = []; - editStack.future = []; + editStack.flushAllElements(); return; } - editStack.past.pop(); - editStack.future.push(element); - return this._safeInvoke(element, () => element.actual.undo()); + if (editStack.locked) { + const message = nls.localize('cannotResourceUndoDueToInProgressUndoRedo', "Could not undo '{0}' because there is already an undo or redo operation running.", element.label); + this._notificationService.info(message); + return; + } + editStack.moveBackward(element); + return this._safeInvokeWithLocks(element, () => element.actual.undo(), [editStack]); } public undo(resource: URI): Promise | void { @@ -458,11 +631,11 @@ export class UndoRedoService implements IUndoRedoService { } const editStack = this._editStacks.get(strResource)!; - if (editStack.past.length === 0) { + const element = editStack.getClosestPastElement(); + if (!element) { return; } - const element = editStack.past[editStack.past.length - 1]; if (element.type === UndoRedoElementType.Workspace) { return this._workspaceUndo(resource, element); } else { @@ -474,63 +647,101 @@ export class UndoRedoService implements IUndoRedoService { const strResource = uriGetComparisonKey(resource); if (this._editStacks.has(strResource)) { const editStack = this._editStacks.get(strResource)!; - return (editStack.future.length > 0); + return editStack.hasFutureElements(); } return false; } - private _workspaceRedo(resource: URI, element: WorkspaceStackElement): Promise | void { + private _checkWorkspaceRedo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[], checkInvalidatedResources: boolean): WorkspaceVerificationError | null { if (element.removedResources) { this._splitFutureWorkspaceElement(element, element.removedResources); const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.removedResources.createMessage()); this._notificationService.info(message); - return this.redo(resource); + return new WorkspaceVerificationError(this.redo(resource)); } - if (element.invalidatedResources) { + if (checkInvalidatedResources && element.invalidatedResources) { this._splitFutureWorkspaceElement(element, element.invalidatedResources); const message = nls.localize('cannotWorkspaceRedo', "Could not redo '{0}' across all files. {1}", element.label, element.invalidatedResources.createMessage()); this._notificationService.info(message); - return this.redo(resource); + return new WorkspaceVerificationError(this.redo(resource)); } // this must be the last future element in all the impacted resources! - let affectedEditStacks: ResourceEditStack[] = []; - for (const strResource of element.strResources) { - affectedEditStacks.push(this._editStacks.get(strResource)!); - } - - let cannotRedoDueToResources: URI[] = []; + const cannotRedoDueToResources: URI[] = []; for (const editStack of affectedEditStacks) { - if (editStack.future.length === 0 || editStack.future[editStack.future.length - 1] !== element) { + if (editStack.getClosestFutureElement() !== element) { cannotRedoDueToResources.push(editStack.resource); } } - if (cannotRedoDueToResources.length > 0) { this._splitFutureWorkspaceElement(element, null); const paths = cannotRedoDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path); const message = nls.localize('cannotWorkspaceRedoDueToChanges', "Could not redo '{0}' across all files because changes were made to {1}", element.label, paths.join(', ')); this._notificationService.info(message); - return this.redo(resource); + return new WorkspaceVerificationError(this.redo(resource)); + } + + const cannotLockDueToResources: URI[] = []; + for (const editStack of affectedEditStacks) { + if (editStack.locked) { + cannotLockDueToResources.push(editStack.resource); + } + } + if (cannotLockDueToResources.length > 0) { + this._splitFutureWorkspaceElement(element, null); + const paths = cannotLockDueToResources.map(r => r.scheme === Schemas.file ? r.fsPath : r.path); + const message = nls.localize('cannotWorkspaceRedoDueToInProgressUndoRedo', "Could not redo '{0}' across all files because there is already an undo or redo operation running on {1}", element.label, paths.join(', ')); + this._notificationService.info(message); + return new WorkspaceVerificationError(this.redo(resource)); + } + + return null; + } + + private _workspaceRedo(resource: URI, element: WorkspaceStackElement): Promise | void { + const affectedEditStacks = this._getAffectedEditStacks(element); + const verificationError = this._checkWorkspaceRedo(resource, element, affectedEditStacks, /*invalidated resources will be checked after the prepare call*/false); + if (verificationError) { + return verificationError.returnValue; + } + return this._executeWorkspaceRedo(resource, element, affectedEditStacks); + } + + private async _executeWorkspaceRedo(resource: URI, element: WorkspaceStackElement, affectedEditStacks: ResourceEditStack[]): Promise { + // prepare + let cleanup: IDisposable; + try { + cleanup = await this._invokePrepare(element); + } catch (err) { + return this._onError(err, element); + } + + // At this point, it is possible that the element has been made invalid in the meantime (due to the prepare await) + const verificationError = this._checkWorkspaceRedo(resource, element, affectedEditStacks, /*now also check that there are no more invalidated resources*/true); + if (verificationError) { + cleanup.dispose(); + return verificationError.returnValue; } for (const editStack of affectedEditStacks) { - editStack.future.pop(); - editStack.past.push(element); + editStack.moveForward(element); } - return this._safeInvoke(element, () => element.actual.redo()); + return this._safeInvokeWithLocks(element, () => element.actual.redo(), affectedEditStacks, cleanup); } private _resourceRedo(editStack: ResourceEditStack, element: ResourceStackElement): Promise | void { if (!element.isValid) { // invalid element => immediately flush edit stack! - editStack.past = []; - editStack.future = []; + editStack.flushAllElements(); return; } - editStack.future.pop(); - editStack.past.push(element); - return this._safeInvoke(element, () => element.actual.redo()); + if (editStack.locked) { + const message = nls.localize('cannotResourceRedoDueToInProgressUndoRedo', "Could not redo '{0}' because there is already an undo or redo operation running.", element.label); + this._notificationService.info(message); + return; + } + editStack.moveForward(element); + return this._safeInvokeWithLocks(element, () => element.actual.redo(), [editStack]); } public redo(resource: URI): Promise | void { @@ -540,11 +751,11 @@ export class UndoRedoService implements IUndoRedoService { } const editStack = this._editStacks.get(strResource)!; - if (editStack.future.length === 0) { + const element = editStack.getClosestFutureElement(); + if (!element) { return; } - const element = editStack.future[editStack.future.length - 1]; if (element.type === UndoRedoElementType.Workspace) { return this._workspaceRedo(resource, element); } else { @@ -553,4 +764,8 @@ export class UndoRedoService implements IUndoRedoService { } } +class WorkspaceVerificationError { + constructor(public readonly returnValue: Promise | void) { } +} + registerSingleton(IUndoRedoService, UndoRedoService); diff --git a/src/vs/platform/url/common/urlService.ts b/src/vs/platform/url/common/urlService.ts index 030d52b587e..dbcac93deff 100644 --- a/src/vs/platform/url/common/urlService.ts +++ b/src/vs/platform/url/common/urlService.ts @@ -8,6 +8,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { values } from 'vs/base/common/map'; import { first } from 'vs/base/common/async'; import { toDisposable, IDisposable, Disposable } from 'vs/base/common/lifecycle'; +import product from 'vs/platform/product/common/product'; export abstract class AbstractURLService extends Disposable implements IURLService { @@ -27,3 +28,16 @@ export abstract class AbstractURLService extends Disposable implements IURLServi return toDisposable(() => this.handlers.delete(handler)); } } + +export class NativeURLService extends AbstractURLService { + + create(options?: Partial): URI { + let { authority, path, query, fragment } = options ? options : { authority: undefined, path: undefined, query: undefined, fragment: undefined }; + + if (authority && path && path.indexOf('/') !== 0) { + path = `/${path}`; // URI validation requires a path if there is an authority + } + + return URI.from({ scheme: product.urlProtocol, authority, path, query, fragment }); + } +} diff --git a/src/vs/platform/url/node/urlService.ts b/src/vs/platform/url/node/urlService.ts deleted file mode 100644 index a0c9249dd7d..00000000000 --- a/src/vs/platform/url/node/urlService.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { URI, UriComponents } from 'vs/base/common/uri'; -import product from 'vs/platform/product/common/product'; -import { AbstractURLService } from 'vs/platform/url/common/urlService'; - -export class URLService extends AbstractURLService { - - create(options?: Partial): URI { - let { authority, path, query, fragment } = options ? options : { authority: undefined, path: undefined, query: undefined, fragment: undefined }; - - if (authority && path && path.indexOf('/') !== 0) { - path = `/${path}`; // URI validation requires a path if there is an authority - } - - return URI.from({ scheme: product.urlProtocol, authority, path, query, fragment }); - } -} diff --git a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts index 433461b6c7e..d8d5d0dd876 100644 --- a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts +++ b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts @@ -238,7 +238,7 @@ export abstract class AbstractSynchroniser extends Disposable { if (remoteUserData.syncData && remoteUserData.syncData.version > this.version) { // current version is not compatible with cloud version this.telemetryService.publicLog2<{ source: string }, SyncSourceClassification>('sync/incompatible', { source: this.resource }); - throw new UserDataSyncError(localize('incompatible', "Cannot sync {0} as its version {1} is not compatible with cloud {2}", this.resource, this.version, remoteUserData.syncData.version), UserDataSyncErrorCode.Incompatible, this.resource); + throw new UserDataSyncError(localize({ key: 'incompatible', comment: ['This is an error while syncing a resource that its local version is not compatible with its remote version.'] }, "Cannot sync {0} as its local version {1} is not compatible with its remote version {2}", this.resource, this.version, remoteUserData.syncData.version), UserDataSyncErrorCode.Incompatible, this.resource); } try { const status = await this.performSync(remoteUserData, lastSyncUserData); diff --git a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts index 20d27834d3f..fe39994eb00 100644 --- a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts @@ -53,7 +53,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto } } else { if (this.autoSync.value !== undefined) { - this.logService.trace('Auto Sync: Disabled because', reason); + this.logService.info('Auto Sync: Disabled because', reason); this.autoSync.clear(); } } @@ -173,6 +173,7 @@ class AutoSync extends Disposable { try { await this.userDataSyncService.sync(); } catch (e) { + this.logService.error(e); error = e; } this._onDidFinishSync.fire(error); diff --git a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts index 344d98aa553..3778148041d 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts @@ -19,7 +19,6 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { assign } from 'vs/base/common/objects'; import { generateUuid } from 'vs/base/common/uuid'; import { isWeb } from 'vs/base/common/platform'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; const USER_SESSION_ID_KEY = 'sync.user-session-id'; const MACHINE_SESSION_ID_KEY = 'sync.machine-session-id'; @@ -43,7 +42,6 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn @IEnvironmentService environmentService: IEnvironmentService, @IFileService fileService: IFileService, @IStorageService private readonly storageService: IStorageService, - @ITelemetryService telemetryService: ITelemetryService, ) { super(); this.userDataSyncStore = getUserDataSyncStore(productService, configurationService); @@ -314,7 +312,6 @@ export class RequestsSession { } if (this.count >= this.limit) { - throw new UserDataSyncStoreError(`Too many requests. Allowed only ${this.limit} requests in ${this.interval / (1000 * 60)} minutes.`, UserDataSyncErrorCode.LocalTooManyRequests); } diff --git a/src/vs/platform/userDataSync/electron-browser/userDataAutoSyncService.ts b/src/vs/platform/userDataSync/electron-browser/userDataAutoSyncService.ts index 6fa694e1d27..04c5fa7f6e2 100644 --- a/src/vs/platform/userDataSync/electron-browser/userDataAutoSyncService.ts +++ b/src/vs/platform/userDataSync/electron-browser/userDataAutoSyncService.ts @@ -5,7 +5,7 @@ import { IUserDataSyncService, IUserDataSyncLogService, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync'; import { Event } from 'vs/base/common/event'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { UserDataAutoSyncService as BaseUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataAutoSyncService'; import { IAuthenticationTokenService } from 'vs/platform/authentication/common/authentication'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index c8b432f5416..f7860aa7ea4 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -8,6 +8,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' import { URI, UriComponents } from 'vs/base/common/uri'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ThemeType } from 'vs/platform/theme/common/themeService'; +import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; export interface IBaseOpenWindowsOptions { forceReuseWindow?: boolean; @@ -18,6 +19,25 @@ export interface IOpenWindowOptions extends IBaseOpenWindowsOptions { preferNewWindow?: boolean; noRecentEntry?: boolean; + + diffMode?: boolean; + gotoLineMode?: boolean; +} + +export interface INativeOpenWindowOptions extends IOpenWindowOptions { + diffMode?: boolean; + addMode?: boolean; + gotoLineMode?: boolean; + waitMarkerFileURI?: URI; +} + +export interface IOpenedWindow { + id: number; + workspace?: IWorkspaceIdentifier; + folderUri?: ISingleFolderWorkspaceIdentifier; + title: string; + filename?: string; + dirty: boolean; } export interface IOpenEmptyWindowOptions extends IBaseOpenWindowsOptions { diff --git a/src/vs/code/node/activeWindowTracker.ts b/src/vs/platform/windows/electron-main/windowTracker.ts similarity index 86% rename from src/vs/code/node/activeWindowTracker.ts rename to src/vs/platform/windows/electron-main/windowTracker.ts index a7dbeb98bf2..f9c5c9fe055 100644 --- a/src/vs/code/node/activeWindowTracker.ts +++ b/src/vs/platform/windows/electron-main/windowTracker.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Event } from 'vs/base/common/event'; -import { DisposableStore, Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronMainService } from 'vs/platform/electron/electron-main/electronMainService'; export class ActiveWindowManager extends Disposable { @@ -15,7 +15,7 @@ export class ActiveWindowManager extends Disposable { private activeWindowId: number | undefined; - constructor(@IElectronService electronService: IElectronService) { + constructor(@IElectronMainService electronService: IElectronMainService) { super(); // remember last active window id upon events @@ -23,7 +23,7 @@ export class ActiveWindowManager extends Disposable { onActiveWindowChange(this.setActiveWindow, this, this.disposables); // resolve current active window - this.firstActiveWindowIdPromise = createCancelablePromise(() => electronService.getActiveWindowId()); + this.firstActiveWindowIdPromise = createCancelablePromise(() => electronService.getActiveWindowId(-1)); (async () => { try { const windowId = await this.firstActiveWindowIdPromise; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index cdd6731748d..58ba2a8ae86 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -16,7 +16,6 @@ import { INativeEnvironmentService } from 'vs/platform/environment/node/environm import { IStateService } from 'vs/platform/state/node/state'; import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; import { ipcMain as ipc, screen, BrowserWindow, MessageBoxOptions, Display, app, nativeTheme } from 'electron'; -import { parseLineAndColumnAware } from 'vs/code/node/paths'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; @@ -39,7 +38,7 @@ import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { isWindowsDriveLetter, toSlashes } from 'vs/base/common/extpath'; +import { isWindowsDriveLetter, toSlashes, parseLineAndColumnAware } from 'vs/base/common/extpath'; import { CharCode } from 'vs/base/common/charCode'; export interface IWindowState { diff --git a/src/vs/platform/windows/node/window.ts b/src/vs/platform/windows/node/window.ts index cf737ec23b4..13d68b48a84 100644 --- a/src/vs/platform/windows/node/window.ts +++ b/src/vs/platform/windows/node/window.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IOpenWindowOptions, IWindowConfiguration, IPath, IOpenFileRequest, IPathData } from 'vs/platform/windows/common/windows'; +import { IWindowConfiguration, IPath, IOpenFileRequest, IPathData } from 'vs/platform/windows/common/windows'; import { URI, UriComponents } from 'vs/base/common/uri'; import * as platform from 'vs/base/common/platform'; import * as extpath from 'vs/base/common/extpath'; @@ -13,15 +13,6 @@ import { LogLevel } from 'vs/platform/log/common/log'; import { ExportData } from 'vs/base/common/performance'; import { ParsedArgs } from 'vs/platform/environment/node/argv'; -export interface IOpenedWindow { - id: number; - workspace?: IWorkspaceIdentifier; - folderUri?: ISingleFolderWorkspaceIdentifier; - title: string; - filename?: string; - dirty: boolean; -} - export const enum OpenContext { // opening when running from the command line @@ -100,13 +91,6 @@ export interface IPathsToWaitForData { waitMarkerFileUri: UriComponents; } -export interface INativeOpenWindowOptions extends IOpenWindowOptions { - diffMode?: boolean; - addMode?: boolean; - gotoLineMode?: boolean; - waitMarkerFileURI?: URI; -} - export interface IWindowContext { openedWorkspace?: IWorkspaceIdentifier; openedFolderUri?: URI; diff --git a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts index 2356a099f18..96f8c6c93ad 100644 --- a/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts +++ b/src/vs/platform/workspaces/test/electron-main/workspacesMainService.test.ts @@ -19,7 +19,7 @@ import { isWindows } from 'vs/base/common/platform'; import { normalizeDriveLetter } from 'vs/base/common/labels'; import { dirname, joinPath } from 'vs/base/common/resources'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; +import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { IBackupMainService, IWorkspaceBackupInfo } from 'vs/platform/backup/electron-main/backup'; import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup'; diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index c650293762e..8bf4f02140c 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -2645,7 +2645,6 @@ declare module 'vscode' { TypeParameter = 25 } - /** * Symbol tags are extra annotations that tweak the rendering of a symbol. */ @@ -3055,7 +3054,6 @@ declare module 'vscode' { */ renameFile(oldUri: Uri, newUri: Uri, options?: { overwrite?: boolean, ignoreIfExists?: boolean }, metadata?: WorkspaceEditEntryMetadata): void; - /** * Get all text edits grouped by resource. * @@ -3952,9 +3950,13 @@ declare module 'vscode' { * * The editor will only resolve a completion item once. * - * *Note* that accepting a completion item will not wait for it to be resolved. Because of that [`insertText`](#CompletionItem.insertText), - * [`additionalTextEdits`](#CompletionItem.additionalTextEdits), and [`command`](#CompletionItem.command) should not - * be changed when resolving an item. + * *Note* that this function is called when completion items are already showing in the UI or when an item has been + * selected for insertion. Because of that, no property that changes the presentation (label, sorting, filtering etc) + * or the (primary) insert behaviour ([insertText](#CompletionItem.insertText)) can be changed. + * + * This function may fill in [additionalTextEdits](#CompletionItem.additionalTextEdits). However, that means an item might be + * inserted *before* resolving is done and in that case the editor will do a best effort to still apply those additional + * text edits. * * @param item A completion item currently active in the UI. * @param token A cancellation token. @@ -3964,7 +3966,6 @@ declare module 'vscode' { resolveCompletionItem?(item: T, token: CancellationToken): ProviderResult; } - /** * A document link is a range in a text document that links to an internal or external resource, like another * text document or a web site. @@ -5657,7 +5658,6 @@ declare module 'vscode' { private constructor(id: string, label: string); } - /** * A structure that defines a task kind in the system. * The value must be JSON-stringifyable. @@ -8957,7 +8957,6 @@ declare module 'vscode' { readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>; } - /** * An event describing a change to the set of [workspace folders](#workspace.workspaceFolders). */ @@ -9745,8 +9744,8 @@ declare module 'vscode' { * Register a rename provider. * * Multiple providers can be registered for a language. In that case providers are sorted - * by their [score](#languages.match) and the best-matching provider is used. Failure - * of the selected provider will cause a failure of the whole operation. + * by their [score](#languages.match) and asked in sequence. The first provider producing a result + * defines the result of the whole operation. * * @param selector A selector that defines the documents this provider is applicable to. * @param provider A rename provider. @@ -10641,7 +10640,6 @@ declare module 'vscode' { */ export let breakpoints: Breakpoint[]; - /** * An [event](#Event) which fires when the [active debug session](#debug.activeDebugSession) * has changed. *Note* that the event also fires when the active debug session changes diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index bb3a911e0f1..7a1302fecb1 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -78,7 +78,6 @@ declare module 'vscode' { readonly removed: string[]; } - /** * Options to be used when getting a session from an [AuthenticationProvider](#AuthenticationProvider). */ @@ -1018,8 +1017,6 @@ declare module 'vscode' { //#endregion - - //#region Terminal link handlers https://github.com/microsoft/vscode/issues/91606 export namespace window { @@ -1534,7 +1531,6 @@ declare module 'vscode' { export interface CustomTextEditorProvider { - /** * Handle when the underlying resource for a custom editor is renamed. * @@ -1552,7 +1548,6 @@ declare module 'vscode' { //#endregion - //#region allow QuickPicks to skip sorting: https://github.com/microsoft/vscode/issues/73904 export interface QuickPick extends QuickInput { @@ -1841,7 +1836,6 @@ declare module 'vscode' { preloads?: Uri[]; } - export interface NotebookCellsChangeData { readonly start: number; readonly deletedCount: number; @@ -2040,7 +2034,6 @@ declare module 'vscode' { //#endregion - //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 export class TimelineItem { @@ -2273,7 +2266,6 @@ declare module 'vscode' { //#endregion - //#region https://github.com/microsoft/vscode/issues/91555 export enum StandardTokenType { diff --git a/src/vs/workbench/api/browser/mainThreadDocuments.ts b/src/vs/workbench/api/browser/mainThreadDocuments.ts index 68454e67aca..f0138dc77cb 100644 --- a/src/vs/workbench/api/browser/mainThreadDocuments.ts +++ b/src/vs/workbench/api/browser/mainThreadDocuments.ts @@ -10,17 +10,18 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services/modelService'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { IFileService } from 'vs/platform/files/common/files'; +import { IFileService, FileOperation } from 'vs/platform/files/common/files'; import { MainThreadDocumentsAndEditors } from 'vs/workbench/api/browser/mainThreadDocumentsAndEditors'; import { ExtHostContext, ExtHostDocumentsShape, IExtHostContext, MainThreadDocumentsShape } from 'vs/workbench/api/common/extHost.protocol'; import { ITextEditorModel } from 'vs/workbench/common/editor'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { toLocalResource } from 'vs/base/common/resources'; +import { toLocalResource, isEqualOrParent } from 'vs/base/common/resources'; +import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; export class BoundModelReferenceCollection { - private _data = new Array<{ length: number, dispose(): void }>(); + private _data = new Array<{ uri: URI, length: number, dispose(): void }>(); private _length = 0; constructor( @@ -34,10 +35,18 @@ export class BoundModelReferenceCollection { this._data = dispose(this._data); } - add(ref: IReference): void { + remove(uri: URI): void { + for (const entry of [...this._data] /* copy array because dispose will modify it */) { + if (isEqualOrParent(entry.uri, uri)) { + entry.dispose(); + } + } + } + + add(uri: URI, ref: IReference): void { const length = ref.object.textEditorModel.getValueLength(); let handle: any; - let entry: { length: number, dispose(): void }; + let entry: { uri: URI, length: number, dispose(): void }; const dispose = () => { const idx = this._data.indexOf(entry); if (idx >= 0) { @@ -48,7 +57,7 @@ export class BoundModelReferenceCollection { } }; handle = setTimeout(dispose, this._maxAge); - entry = { length, dispose }; + entry = { uri, length, dispose }; this._data.push(entry); this._length += length; @@ -74,7 +83,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { private _modelToDisposeMap: { [modelUrl: string]: IDisposable; }; private readonly _proxy: ExtHostDocumentsShape; private readonly _modelIsSynced = new Set(); - private _modelReferenceCollection = new BoundModelReferenceCollection(); + private readonly _modelReferenceCollection = new BoundModelReferenceCollection(); constructor( documentsAndEditors: MainThreadDocumentsAndEditors, @@ -83,7 +92,8 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { @ITextFileService textFileService: ITextFileService, @IFileService fileService: IFileService, @ITextModelService textModelResolverService: ITextModelService, - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService ) { this._modelService = modelService; this._textModelResolverService = textModelResolverService; @@ -109,6 +119,12 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { } })); + this._toDispose.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => { + if (e.source && (e.operation === FileOperation.MOVE || e.operation === FileOperation.DELETE)) { + this._modelReferenceCollection.remove(e.source); + } + })); + this._modelToDisposeMap = Object.create(null); } @@ -199,7 +215,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape { private _handleAsResourceInput(uri: URI): Promise { return this._textModelResolverService.createModelReference(uri).then(ref => { - this._modelReferenceCollection.add(ref); + this._modelReferenceCollection.add(uri, ref); const result = !!ref.object; return result; }); diff --git a/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts b/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts index 78da88e8955..5d430ea017d 100644 --- a/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts @@ -27,6 +27,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; namespace delta { @@ -326,11 +327,12 @@ export class MainThreadDocumentsAndEditors { @IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService, @IBulkEditService bulkEditService: IBulkEditService, @IPanelService panelService: IPanelService, - @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService + @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, + @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentsAndEditors); - const mainThreadDocuments = this._toDispose.add(new MainThreadDocuments(this, extHostContext, this._modelService, this._textFileService, fileService, textModelResolverService, environmentService)); + const mainThreadDocuments = this._toDispose.add(new MainThreadDocuments(this, extHostContext, this._modelService, this._textFileService, fileService, textModelResolverService, environmentService, workingCopyFileService)); extHostContext.set(MainContext.MainThreadDocuments, mainThreadDocuments); const mainThreadTextEditors = this._toDispose.add(new MainThreadTextEditors(this, extHostContext, codeEditorService, bulkEditService, this._editorService, this._editorGroupService)); diff --git a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts index d88424433fb..aec20a76da9 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystemEventService.ts @@ -8,12 +8,9 @@ import { FileChangeType, IFileService, FileOperation } from 'vs/platform/files/c import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { ExtHostContext, FileSystemEvents, IExtHostContext } from '../common/extHost.protocol'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { IProgressService } from 'vs/platform/progress/common/progress'; import { localize } from 'vs/nls'; import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ILogService } from 'vs/platform/log/common/log'; import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; @extHostCustomer @@ -25,9 +22,6 @@ export class MainThreadFileSystemEventService { extHostContext: IExtHostContext, @IFileService fileService: IFileService, @ITextFileService textFileService: ITextFileService, - @IProgressService progressService: IProgressService, - @IConfigurationService configService: IConfigurationService, - @ILogService logService: ILogService, @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService ) { diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index e9f673616bf..54e67c584d3 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -35,6 +35,7 @@ export class MainThreadNotebookDocument extends Disposable { this._textModel = new NotebookTextModel(handle, viewType, uri); this._register(this._textModel.onDidModelChange(e => { this._proxy.$acceptModelChanged(this.uri, e); + this._proxy.$acceptEditorPropertiesChanged(uri, { selections: { selections: this._textModel.selections }, metadata: null }); })); this._register(this._textModel.onDidSelectionChange(e => { const selectionsChange = e ? { selections: e } : null; diff --git a/src/vs/workbench/api/common/extHostDecorations.ts b/src/vs/workbench/api/common/extHostDecorations.ts index cccb18f5fa9..9ed26739e6d 100644 --- a/src/vs/workbench/api/common/extHostDecorations.ts +++ b/src/vs/workbench/api/common/extHostDecorations.ts @@ -9,10 +9,10 @@ import { MainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, Decor import { Disposable, Decoration } from 'vs/workbench/api/common/extHostTypes'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { asArray } from 'vs/base/common/arrays'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { ILogService } from 'vs/platform/log/common/log'; +import { asArray } from 'vs/base/common/arrays'; interface ProviderData { provider: vscode.DecorationProvider; @@ -40,7 +40,9 @@ export class ExtHostDecorations implements IExtHostDecorations { this._proxy.$registerDecorationProvider(handle, extensionId.value); const listener = provider.onDidChangeDecorations(e => { - this._proxy.$onDidChange(handle, !e ? null : asArray(e)); + this._proxy.$onDidChange(handle, !e || (Array.isArray(e) && e.length > 250) + ? null + : asArray(e)); }); return new Disposable(() => { diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 13697b1e1ed..a114726c453 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -857,16 +857,11 @@ class SuggestAdapter { private _cache = new Cache('CompletionItem'); private _disposables = new Map(); - private _didWarnMust: boolean = false; - private _didWarnShould: boolean = false; - constructor( private readonly _documents: ExtHostDocuments, private readonly _commands: CommandsConverter, private readonly _provider: vscode.CompletionItemProvider, - private readonly _logService: ILogService, private readonly _apiDeprecation: IExtHostApiDeprecationService, - private readonly _telemetry: extHostProtocol.MainThreadTelemetryShape, private readonly _extension: IExtensionDescription, ) { } @@ -930,41 +925,12 @@ class SuggestAdapter { return undefined; } - const _mustNotChange = SuggestAdapter._mustNotChangeHash(item); - const _mayNotChange = SuggestAdapter._mayNotChangeHash(item); - const resolvedItem = await asPromise(() => this._provider.resolveCompletionItem!(item, token)); if (!resolvedItem) { return undefined; } - type BlameExtension = { - extensionId: string; - kind: string; - index: string; - }; - - type BlameExtensionMeta = { - extensionId: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; - kind: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; - index: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' }; - }; - - let _mustNotChangeIndex = !this._didWarnMust && SuggestAdapter._mustNotChangeDiff(_mustNotChange, resolvedItem); - if (typeof _mustNotChangeIndex === 'string') { - this._logService.warn(`[${this._extension.identifier.value}] INVALID result from 'resolveCompletionItem', extension MUST NOT change any of: label, sortText, filterText, insertText, or textEdit`); - this._telemetry.$publicLog2('badresolvecompletion', { extensionId: this._extension.identifier.value, kind: 'must', index: _mustNotChangeIndex }); - this._didWarnMust = true; - } - - let _mayNotChangeIndex = !this._didWarnShould && SuggestAdapter._mayNotChangeDiff(_mayNotChange, resolvedItem); - if (typeof _mayNotChangeIndex === 'string') { - this._logService.info(`[${this._extension.identifier.value}] UNSAVE result from 'resolveCompletionItem', extension SHOULD NOT change any of: additionalTextEdits, or command`); - this._telemetry.$publicLog2('badresolvecompletion', { extensionId: this._extension.identifier.value, kind: 'should', index: _mayNotChangeIndex }); - this._didWarnShould = true; - } - return this._convertCompletionItem(resolvedItem, id); } @@ -1035,45 +1001,6 @@ class SuggestAdapter { return result; } - - private static _mustNotChangeHash(item: vscode.CompletionItem) { - const res = JSON.stringify([item.label, item.sortText, item.filterText, item.insertText, item.range]); - return res; - } - - private static _mustNotChangeDiff(hash: string, item: vscode.CompletionItem): string | void { - const thisArr = [item.label, item.sortText, item.filterText, item.insertText, item.range]; - const thisHash = JSON.stringify(thisArr); - if (hash === thisHash) { - return; - } - const arr = JSON.parse(hash); - for (let i = 0; i < 6; i++) { - if (JSON.stringify(arr[i] !== JSON.stringify(thisArr[i]))) { - return i.toString(); - } - } - return 'unknown'; - } - - private static _mayNotChangeHash(item: vscode.CompletionItem) { - return JSON.stringify([item.additionalTextEdits, item.command]); - } - - private static _mayNotChangeDiff(hash: string, item: vscode.CompletionItem): string | void { - const thisArr = [item.additionalTextEdits, item.command]; - const thisHash = JSON.stringify(thisArr); - if (hash === thisHash) { - return; - } - const arr = JSON.parse(hash); - for (let i = 0; i < 6; i++) { - if (JSON.stringify(arr[i] !== JSON.stringify(thisArr[i]))) { - return i.toString(); - } - } - return 'unknown'; - } } class SignatureHelpAdapter { @@ -1392,7 +1319,6 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF private readonly _uriTransformer: IURITransformer | null; private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape; - private readonly _telemetryShape: extHostProtocol.MainThreadTelemetryShape; private _documents: ExtHostDocuments; private _commands: ExtHostCommands; private _diagnostics: ExtHostDiagnostics; @@ -1411,7 +1337,6 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF ) { this._uriTransformer = uriTransformer; this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadLanguageFeatures); - this._telemetryShape = mainContext.getProxy(extHostProtocol.MainContext.MainThreadTelemetry); this._documents = documents; this._commands = commands; this._diagnostics = diagnostics; @@ -1780,7 +1705,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF // --- suggestion registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable { - const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._logService, this._apiDeprecation, this._telemetryShape, extension), extension); + const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._apiDeprecation, extension), extension); this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider), extension.identifier); return this._createDisposable(handle); } diff --git a/src/vs/workbench/api/node/extHostCLIServer.ts b/src/vs/workbench/api/node/extHostCLIServer.ts index ad28cc495c0..2a1941271c2 100644 --- a/src/vs/workbench/api/node/extHostCLIServer.ts +++ b/src/vs/workbench/api/node/extHostCLIServer.ts @@ -7,10 +7,9 @@ import { generateRandomPipeName } from 'vs/base/parts/ipc/node/ipc.net'; import * as http from 'http'; import * as fs from 'fs'; import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; -import { IWindowOpenable } from 'vs/platform/windows/common/windows'; +import { IWindowOpenable, INativeOpenWindowOptions } from 'vs/platform/windows/common/windows'; import { URI } from 'vs/base/common/uri'; import { hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces'; -import { INativeOpenWindowOptions } from 'vs/platform/windows/node/window'; import { ILogService } from 'vs/platform/log/common/log'; export interface OpenCommandPipeArgs { diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 6312c90b200..88371fe8b4c 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -687,7 +687,7 @@ export class MoveFocusedViewAction extends Action { const quickPick = this.quickInputService.createQuickPick(); quickPick.placeholder = nls.localize('moveFocusedView.selectDestination', "Select a Destination for the View"); - quickPick.title = nls.localize('moveFocusedView.title', "View: Move {0}", viewDescriptor.name); + quickPick.title = nls.localize({ key: 'moveFocusedView.title', comment: ['{0} indicates the title of the view the user has selected to move.'] }, "View: Move {0}", viewDescriptor.name); const items: Array = []; const currentContainer = this.viewDescriptorService.getViewContainerByViewId(focusedViewId)!; diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index dde922f9908..6f17fd71773 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -9,7 +9,6 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { dispose, IDisposable, Disposable, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Part } from 'vs/workbench/browser/part'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -726,7 +725,6 @@ class StatusbarEntryItem extends Disposable { @ICommandService private readonly commandService: ICommandService, @INotificationService private readonly notificationService: INotificationService, @ITelemetryService private readonly telemetryService: ITelemetryService, - @IEditorService private readonly editorService: IEditorService, @IThemeService private readonly themeService: IThemeService ) { super(); @@ -829,12 +827,6 @@ class StatusbarEntryItem extends Disposable { const id = typeof command === 'string' ? command : command.id; const args = typeof command === 'string' ? [] : command.arguments ?? []; - // Maintain old behaviour of always focusing the editor here - const activeTextEditorControl = this.editorService.activeTextEditorControl; - if (activeTextEditorControl) { - activeTextEditorControl.focus(); - } - this.telemetryService.publicLog2('workbenchActionExecuted', { id, from: 'status bar' }); try { await this.commandService.executeCommand(id, ...args); diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 5ef6556da13..ad62952a45e 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -377,10 +377,10 @@ export abstract class ViewPane extends Pane implements IView { private calculateTitle(title: string): string { const viewContainer = this.viewDescriptorService.getViewContainerByViewId(this.id)!; const model = this.viewDescriptorService.getViewContainerModel(viewContainer); - const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(this.id)!; + const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(this.id); const isDefault = this.viewDescriptorService.getDefaultContainerById(this.id) === viewContainer; - if (!isDefault && viewDescriptor.containerTitle && model.title !== viewDescriptor.containerTitle) { + if (!isDefault && viewDescriptor?.containerTitle && model.title !== viewDescriptor.containerTitle) { return `${viewDescriptor.containerTitle}: ${title}`; } diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 0a7e94dc9f5..6a8dd33202f 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -237,6 +237,11 @@ export interface IAddedViewDescriptorRef extends IViewDescriptorRef { size?: number; } +export interface IAddedViewDescriptorState { + viewDescriptor: IViewDescriptor, + collapsed?: boolean; +} + export interface IViewContainerModel { readonly title: string; diff --git a/src/vs/workbench/contrib/backup/electron-browser/backup.contribution.ts b/src/vs/workbench/contrib/backup/electron-sandbox/backup.contribution.ts similarity index 96% rename from src/vs/workbench/contrib/backup/electron-browser/backup.contribution.ts rename to src/vs/workbench/contrib/backup/electron-sandbox/backup.contribution.ts index 9868c6285fe..43a574d8bf4 100644 --- a/src/vs/workbench/contrib/backup/electron-browser/backup.contribution.ts +++ b/src/vs/workbench/contrib/backup/electron-sandbox/backup.contribution.ts @@ -6,7 +6,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-browser/backupTracker'; +import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker'; // Register Backup Tracker Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeBackupTracker, LifecyclePhase.Starting); diff --git a/src/vs/workbench/contrib/backup/electron-browser/backupTracker.ts b/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts similarity index 99% rename from src/vs/workbench/contrib/backup/electron-browser/backupTracker.ts rename to src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts index 3048c945dc6..8585de7a240 100644 --- a/src/vs/workbench/contrib/backup/electron-browser/backupTracker.ts +++ b/src/vs/workbench/contrib/backup/electron-sandbox/backupTracker.ts @@ -14,7 +14,7 @@ import Severity from 'vs/base/common/severity'; import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { isMacintosh } from 'vs/base/common/platform'; import { HotExitConfiguration } from 'vs/platform/files/common/files'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { BackupTracker } from 'vs/workbench/contrib/backup/common/backupTracker'; import { ILogService } from 'vs/platform/log/common/log'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts index cab5dd56e4b..68c8751e028 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupRestorer.test.ts @@ -13,7 +13,7 @@ import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { DefaultEndOfLine } from 'vs/editor/common/model'; import { hashPath } from 'vs/workbench/services/backup/node/backupFileService'; -import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-browser/backupTracker'; +import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker'; import { workbenchInstantiationService } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts index ea8c85ea656..485390ddab3 100644 --- a/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts +++ b/src/vs/workbench/contrib/backup/test/electron-browser/backupTracker.test.ts @@ -11,7 +11,7 @@ import * as pfs from 'vs/base/node/pfs'; import { URI } from 'vs/base/common/uri'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { hashPath } from 'vs/workbench/services/backup/node/backupFileService'; -import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-browser/backupTracker'; +import { NativeBackupTracker } from 'vs/workbench/contrib/backup/electron-sandbox/backupTracker'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; @@ -34,7 +34,7 @@ import { HotExitConfiguration } from 'vs/platform/files/common/files'; import { ShutdownReason, ILifecycleService, BeforeShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle'; import { IFileDialogService, ConfirmResult, IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IWorkspaceContextService, Workspace } from 'vs/platform/workspace/common/workspace'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { BackupTracker } from 'vs/workbench/contrib/backup/common/backupTracker'; import { workbenchInstantiationService, TestServiceAccessor } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts index 4a9b99b6971..0b321ee1f68 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditPreview.ts @@ -20,6 +20,7 @@ import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model'; import { ConflictDetector } from 'vs/workbench/services/bulkEdit/browser/conflicts'; import { ResourceMap } from 'vs/base/common/map'; import { localize } from 'vs/nls'; +import { exturi } from 'vs/base/common/resources'; export class CheckedStates { @@ -209,13 +210,13 @@ export class BulkFileOperations { } const insert = (uri: URI, map: Map) => { - let key = uri.toString(); + let key = exturi.getComparisonKey(uri, true); let operation = map.get(key); // rename if (!operation && newToOldUri.has(uri)) { uri = newToOldUri.get(uri)!; - key = uri.toString(); + key = exturi.getComparisonKey(uri, true); operation = map.get(key); } diff --git a/src/vs/workbench/contrib/codeEditor/electron-browser/codeEditor.contribution.ts b/src/vs/workbench/contrib/codeEditor/electron-browser/codeEditor.contribution.ts index 21de3dba004..22513f6ef6c 100644 --- a/src/vs/workbench/contrib/codeEditor/electron-browser/codeEditor.contribution.ts +++ b/src/vs/workbench/contrib/codeEditor/electron-browser/codeEditor.contribution.ts @@ -3,7 +3,4 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import './inputClipboardActions'; -import './sleepResumeRepaintMinimap'; -import './selectionClipboard'; import './startDebugTextMate'; diff --git a/src/vs/platform/files/node/files.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution.ts similarity index 77% rename from src/vs/platform/files/node/files.ts rename to src/vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution.ts index bbb85376228..08763754187 100644 --- a/src/vs/platform/files/node/files.ts +++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution.ts @@ -3,5 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const MIN_MAX_MEMORY_SIZE_MB = 2048; -export const FALLBACK_MAX_MEMORY_SIZE_MB = 4096; +import './inputClipboardActions'; +import './selectionClipboard'; +import './sleepResumeRepaintMinimap'; diff --git a/src/vs/workbench/contrib/codeEditor/electron-browser/inputClipboardActions.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/inputClipboardActions.ts similarity index 100% rename from src/vs/workbench/contrib/codeEditor/electron-browser/inputClipboardActions.ts rename to src/vs/workbench/contrib/codeEditor/electron-sandbox/inputClipboardActions.ts diff --git a/src/vs/workbench/contrib/codeEditor/electron-browser/selectionClipboard.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts similarity index 100% rename from src/vs/workbench/contrib/codeEditor/electron-browser/selectionClipboard.ts rename to src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts diff --git a/src/vs/workbench/contrib/codeEditor/electron-browser/sleepResumeRepaintMinimap.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/sleepResumeRepaintMinimap.ts similarity index 90% rename from src/vs/workbench/contrib/codeEditor/electron-browser/sleepResumeRepaintMinimap.ts rename to src/vs/workbench/contrib/codeEditor/electron-sandbox/sleepResumeRepaintMinimap.ts index 7ade76dcb8d..36e1dba73ac 100644 --- a/src/vs/workbench/contrib/codeEditor/electron-browser/sleepResumeRepaintMinimap.ts +++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/sleepResumeRepaintMinimap.ts @@ -6,7 +6,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { ipcRenderer as ipc } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; class SleepResumeRepaintMinimap implements IWorkbenchContribution { @@ -14,7 +14,7 @@ class SleepResumeRepaintMinimap implements IWorkbenchContribution { constructor( @ICodeEditorService codeEditorService: ICodeEditorService ) { - ipc.on('vscode:osResume', () => { + ipcRenderer.on('vscode:osResume', () => { codeEditorService.listCodeEditors().forEach(editor => editor.render(true)); }); } diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 7aa24cd9522..b3df4f720d6 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -100,7 +100,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as(ViewE id: OpenDebugConsoleAction.ID, keybindings: openPanelKb }, - order: 3, + order: 2, hideIfEmpty: true }, ViewContainerLocation.Panel); diff --git a/src/vs/workbench/contrib/debug/browser/debugHover.ts b/src/vs/workbench/contrib/debug/browser/debugHover.ts index 754fc963e34..72a879b493e 100644 --- a/src/vs/workbench/contrib/debug/browser/debugHover.ts +++ b/src/vs/workbench/contrib/debug/browser/debugHover.ts @@ -341,7 +341,7 @@ class DebugHoverAccessibilityProvider implements IListAccessibilityProvider 0) { - picks.push({ type: 'separator', label: localize('contributed', "contributed") }); + picks.push({ + type: 'separator', label: localize({ + key: 'contributed', + comment: ['contributed is lower case because it looks better like that in UI. Nothing preceeds it. It is a name of the grouping of debug configurations.'] + }, "contributed") + }); } dynamicProviders.forEach(provider => { picks.push({ label: `$(folder) ${provider.label}...`, - ariaLabel: localize('providerAriaLabel', "{0} contributed configurations", provider.label), + ariaLabel: localize({ key: 'providerAriaLabel', comment: ['Placeholder stands for the provider label. For example "NodeJS".'] }, "{0} contributed configurations", provider.label), accept: async () => { const pick = await provider.pick(); if (pick) { diff --git a/src/vs/workbench/contrib/debug/browser/variablesView.ts b/src/vs/workbench/contrib/debug/browser/variablesView.ts index d9c75bd8be4..9f7b7ab5e1a 100644 --- a/src/vs/workbench/contrib/debug/browser/variablesView.ts +++ b/src/vs/workbench/contrib/debug/browser/variablesView.ts @@ -359,7 +359,7 @@ class VariablesAccessibilityProvider implements IListAccessibilityProvider { - s = s.replace(/(["'\\])/g, '\\$1'); + s = s.replace(/(["'\\\$])/g, '\\$1'); return (s.indexOf(' ') >= 0 || s.indexOf(';') >= 0 || s.length === 0) ? `"${s}"` : s; }; diff --git a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentService.test.ts b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentService.test.ts index 54d67cfe69c..a69f5495dc4 100644 --- a/src/vs/workbench/contrib/experiments/test/electron-browser/experimentService.test.ts +++ b/src/vs/workbench/contrib/experiments/test/electron-browser/experimentService.test.ts @@ -15,7 +15,7 @@ import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/exte import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService'; import { Emitter } from 'vs/base/common/event'; import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test'; -import { URLService } from 'vs/platform/url/node/urlService'; +import { NativeURLService } from 'vs/platform/url/common/urlService'; import { IURLService } from 'vs/platform/url/common/url'; import { ITelemetryService, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; @@ -89,7 +89,7 @@ suite('Experiment Service', () => { instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event); instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService)); instantiationService.stub(ITelemetryService, NullTelemetryService); - instantiationService.stub(IURLService, URLService); + instantiationService.stub(IURLService, NativeURLService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); testConfigurationService = new TestConfigurationService(); instantiationService.stub(IConfigurationService, testConfigurationService); diff --git a/src/vs/workbench/contrib/extensions/browser/configBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/configBasedRecommendations.ts index c092c7c81ea..9bb5657c0cc 100644 --- a/src/vs/workbench/contrib/extensions/browser/configBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/configBasedRecommendations.ts @@ -7,7 +7,6 @@ import { IExtensionTipsService, IExtensionManagementService, ILocalExtension, IC import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations'; import { localize } from 'vs/nls'; -import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; @@ -75,7 +74,7 @@ export class ConfigBasedRecommendations extends ExtensionRecommendations { return; } - const local = await this.extensionManagementService.getInstalled(ExtensionType.User); + const local = await this.extensionManagementService.getInstalled(); const { uninstalled } = this.groupByInstalled(distinct(this.importantTips.map(({ extensionId }) => extensionId)), local); if (uninstalled.length === 0) { return; diff --git a/src/vs/workbench/contrib/extensions/browser/exeBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/exeBasedRecommendations.ts index 92d7e07c4fe..f153ecd7a3a 100644 --- a/src/vs/workbench/contrib/extensions/browser/exeBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/exeBasedRecommendations.ts @@ -9,7 +9,6 @@ import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/ import { timeout } from 'vs/base/common/async'; import { localize } from 'vs/nls'; import { IStringDictionary } from 'vs/base/common/collections'; -import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { basename } from 'vs/base/common/path'; @@ -61,7 +60,7 @@ export class ExeBasedRecommendations extends ExtensionRecommendations { importantExeBasedRecommendations[tip.extensionId.toLowerCase()] = tip; }); - const local = await this.extensionManagementService.getInstalled(ExtensionType.User); + const local = await this.extensionManagementService.getInstalled(); const { installed, uninstalled } = this.groupByInstalled(Object.keys(importantExeBasedRecommendations), local); /* Log installed and uninstalled exe based recommendations */ diff --git a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts index af198f44531..527d8180ca3 100644 --- a/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.ts @@ -12,7 +12,6 @@ import { ExtensionRecommendationSource, ExtensionRecommendationReason } from 'vs import { IExtensionsViewPaneContainer, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; import { CancellationToken } from 'vs/base/common/cancellation'; import { localize } from 'vs/nls'; -import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IProductService } from 'vs/platform/product/common/productService'; @@ -181,7 +180,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations { return; } - const installed = await this.extensionManagementService.getInstalled(ExtensionType.User); + const installed = await this.extensionManagementService.getInstalled(); if (await this.promptRecommendedExtensionForFileType(recommendationsToPrompt, installed)) { return; } diff --git a/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts b/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts index 84c47be3064..3ce9d79e586 100644 --- a/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts +++ b/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts @@ -30,7 +30,7 @@ export class RemoteExtensionsInstaller extends Disposable implements IWorkbenchC disposable = MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: 'workbench.extensions.installLocalExtensions', - category: localize('remote', "Remote"), + category: localize({ key: 'remote', comment: ['Remote as in remote machine'] }, "Remote"), title: installLocalExtensionsInRemoteAction.label } }); diff --git a/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts b/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts index 4d05b1d420e..b17fd1dec71 100644 --- a/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts +++ b/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.ts @@ -17,7 +17,6 @@ import { EXTENSIONS_CONFIG } from 'vs/workbench/contrib/extensions/common/extens import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken } from 'vs/base/common/cancellation'; import { localize } from 'vs/nls'; -import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { InstallWorkspaceRecommendedExtensionsAction, ShowRecommendedExtensionsAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage'; @@ -105,7 +104,7 @@ export class WorkspaceRecommendations extends ExtensionRecommendations { return; } - let installed = await this.extensionManagementService.getInstalled(ExtensionType.User); + let installed = await this.extensionManagementService.getInstalled(); installed = installed.filter(l => this.extensionEnablementService.getEnablementState(l) !== EnablementState.DisabledByExtensionKind); // Filter extensions disabled by kind const recommendations = allowedRecommendations.filter(({ extensionId }) => installed.every(local => !areSameExtensions({ id: extensionId }, local.identifier))); diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts index 7f988b5c93c..f95e31cd436 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts @@ -12,7 +12,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar'; import { IExtensionHostProfileService, ProfileSessionState } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { randomPort } from 'vs/base/node/ports'; import product from 'vs/platform/product/common/product'; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts index 94a29c5e229..4289877aade 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionsActions.ts @@ -9,7 +9,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { Schemas } from 'vs/base/common/network'; export class OpenExtensionsFolderAction extends Action { diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index cc851c4bc4d..c5144f24436 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -24,7 +24,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { writeFile } from 'vs/base/node/pfs'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { memoize } from 'vs/base/common/decorators'; diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts index ef9b59e46c6..b20db7d9a94 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionRecommendationsService.test.ts @@ -41,7 +41,7 @@ import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { INotificationService, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification'; -import { URLService } from 'vs/platform/url/node/urlService'; +import { NativeURLService } from 'vs/platform/url/common/urlService'; import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService'; import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; @@ -206,7 +206,7 @@ suite('ExtensionRecommendationsService Test', () => { instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event); instantiationService.stub(IWorkbenchExtensionEnablementService, new TestExtensionEnablementService(instantiationService)); instantiationService.stub(ITelemetryService, NullTelemetryService); - instantiationService.stub(IURLService, URLService); + instantiationService.stub(IURLService, NativeURLService); instantiationService.stub(IWorkspaceTagsService, new NoOpWorkspaceTagsService()); instantiationService.stub(IStorageService, new TestStorageService()); instantiationService.stub(ILogService, new NullLogService()); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts index dfe557cec9d..7d55bdfcc36 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts @@ -30,7 +30,7 @@ import { TestContextService } from 'vs/workbench/test/common/workbenchTestServic import { TestSharedProcessService } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; -import { URLService } from 'vs/platform/url/node/urlService'; +import { NativeURLService } from 'vs/platform/url/common/urlService'; import { URI } from 'vs/base/common/uri'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; @@ -105,7 +105,7 @@ async function setupTest() { instantiationService.stub(IExperimentService, instantiationService.createInstance(TestExperimentService)); instantiationService.stub(IExtensionTipsService, instantiationService.createInstance(ExtensionTipsService)); instantiationService.stub(IExtensionRecommendationsService, {}); - instantiationService.stub(IURLService, URLService); + instantiationService.stub(IURLService, NativeURLService); instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', []); instantiationService.stubPromise(IExtensionManagementService, 'getExtensionsReport', []); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts index a9d3ab44f81..82fc05ca3f9 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsViews.test.ts @@ -30,7 +30,7 @@ import { TestMenuService } from 'vs/workbench/test/browser/workbenchTestServices import { TestSharedProcessService } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ILogService, NullLogService } from 'vs/platform/log/common/log'; -import { URLService } from 'vs/platform/url/node/urlService'; +import { NativeURLService } from 'vs/platform/url/common/urlService'; import { URI } from 'vs/base/common/uri'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { SinonStub } from 'sinon'; @@ -142,7 +142,7 @@ suite('ExtensionsListView Tests', () => { return reasons; } }); - instantiationService.stub(IURLService, URLService); + instantiationService.stub(IURLService, NativeURLService); }); setup(async () => { diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index 48af67b6e03..f7d70b79416 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -32,7 +32,7 @@ import { ILogService, NullLogService } from 'vs/platform/log/common/log'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { ProgressService } from 'vs/workbench/services/progress/browser/progressService'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { URLService } from 'vs/platform/url/node/urlService'; +import { NativeURLService } from 'vs/platform/url/common/urlService'; import { URI } from 'vs/base/common/uri'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionType } from 'vs/platform/extensions/common/extensions'; @@ -72,7 +72,7 @@ suite('ExtensionsWorkbenchServiceTest', () => { instantiationService.stub(IProductService, {}); instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService); - instantiationService.stub(IURLService, URLService); + instantiationService.stub(IURLService, NativeURLService); instantiationService.stub(ISharedProcessService, TestSharedProcessService); instantiationService.stub(IWorkspaceContextService, new TestContextService()); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index 4ef2a0dd098..b30f36916e5 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -144,9 +144,9 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingWeight.WorkbenchContrib + explorerCommandsWeightBonus, when: ContextKeyExpr.and(FilesExplorerFocusCondition, ExplorerResourceCut), primary: KeyCode.Escape, - handler: (accessor: ServicesAccessor) => { + handler: async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); - explorerService.setToCopy([], true); + await explorerService.setToCopy([], true); } }); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 2b4911f6fde..21071623023 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -1060,20 +1060,20 @@ export const deleteFileHandler = async (accessor: ServicesAccessor) => { }; let pasteShouldMove = false; -export const copyFileHandler = (accessor: ServicesAccessor) => { +export const copyFileHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); const stats = explorerService.getContext(true); if (stats.length > 0) { - explorerService.setToCopy(stats, false); + await explorerService.setToCopy(stats, false); pasteShouldMove = false; } }; -export const cutFileHandler = (accessor: ServicesAccessor) => { +export const cutFileHandler = async (accessor: ServicesAccessor) => { const explorerService = accessor.get(IExplorerService); const stats = explorerService.getContext(true); if (stats.length > 0) { - explorerService.setToCopy(stats, true); + await explorerService.setToCopy(stats, true); pasteShouldMove = true; } }; @@ -1140,7 +1140,7 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => { const configurationService = accessor.get(IConfigurationService); const context = explorerService.getContext(true); - const toPaste = resources.distinctParents(clipboardService.readResources(), r => r); + const toPaste = resources.distinctParents(await clipboardService.readResources(), r => r); const element = context.length ? context[0] : explorerService.roots[0]; // Check if target is ancestor of pasted folder @@ -1178,7 +1178,7 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => { if (pasteShouldMove) { // Cut is done. Make sure to clear cut state. - explorerService.setToCopy([], false); + await explorerService.setToCopy([], false); pasteShouldMove = false; } if (stats.length >= 1) { diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 01e0db2c640..457b02dc588 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -471,7 +471,7 @@ export class ExplorerView extends ViewPane { } } - private onContextMenu(e: ITreeContextMenuEvent): void { + private async onContextMenu(e: ITreeContextMenuEvent): Promise { const disposables = new DisposableStore(); let stat = e.element; let anchor = e.anchor; @@ -490,7 +490,7 @@ export class ExplorerView extends ViewPane { } // update dynamic contexts - this.fileCopiedContextKey.set(this.clipboardService.hasResources()); + this.fileCopiedContextKey.set(await this.clipboardService.hasResources()); this.setContextKeys(stat); const selection = this.tree.getSelection(); diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index aed65162f39..37ec584ac78 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -1028,6 +1028,8 @@ export class FileDragAndDrop implements ITreeDragAndDrop { // Handle folder upload else { + + // Create target folder await this.fileService.createFolder(resource); // Recursive upload files in this directory diff --git a/src/vs/workbench/contrib/files/common/explorerService.ts b/src/vs/workbench/contrib/files/common/explorerService.ts index a411f52ba7b..616c81daf57 100644 --- a/src/vs/workbench/contrib/files/common/explorerService.ts +++ b/src/vs/workbench/contrib/files/common/explorerService.ts @@ -126,10 +126,10 @@ export class ExplorerService implements IExplorerService { await this.view.setEditable(stat, isEditing); } - setToCopy(items: ExplorerItem[], cut: boolean): void { + async setToCopy(items: ExplorerItem[], cut: boolean): Promise { const previouslyCutItems = this.cutItems; this.cutItems = cut ? items : undefined; - this.clipboardService.writeResources(items.map(s => s.resource)); + await this.clipboardService.writeResources(items.map(s => s.resource)); this.view?.itemsCopied(items, cut, previouslyCutItems); } diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index d9e592b2779..c970d8a04b7 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -51,7 +51,7 @@ export interface IExplorerService { isEditable(stat: ExplorerItem | undefined): boolean; findClosest(resource: URI): ExplorerItem | null; refresh(): Promise; - setToCopy(stats: ExplorerItem[], cut: boolean): void; + setToCopy(stats: ExplorerItem[], cut: boolean): Promise; isCut(stat: ExplorerItem): boolean; /** diff --git a/src/vs/workbench/contrib/files/electron-browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts similarity index 97% rename from src/vs/workbench/contrib/files/electron-browser/fileActions.contribution.ts rename to src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts index 52b1cf0897f..a335946a0d5 100644 --- a/src/vs/workbench/contrib/files/electron-browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts @@ -9,7 +9,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { isWindows, isMacintosh } from 'vs/base/common/platform'; import { Schemas } from 'vs/base/common/network'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; @@ -17,7 +17,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files'; import { IListService } from 'vs/platform/list/browser/listService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-browser/fileCommands'; +import { revealResourcesInOS } from 'vs/workbench/contrib/files/electron-sandbox/fileCommands'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/workbench/contrib/files/browser/fileActions.contribution'; diff --git a/src/vs/workbench/contrib/files/electron-browser/fileCommands.ts b/src/vs/workbench/contrib/files/electron-sandbox/fileCommands.ts similarity index 94% rename from src/vs/workbench/contrib/files/electron-browser/fileCommands.ts rename to src/vs/workbench/contrib/files/electron-sandbox/fileCommands.ts index 274ee632713..e941d1ece27 100644 --- a/src/vs/workbench/contrib/files/electron-browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/fileCommands.ts @@ -9,7 +9,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { sequence } from 'vs/base/common/async'; import { Schemas } from 'vs/base/common/network'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; // Commands diff --git a/src/vs/workbench/contrib/files/electron-browser/files.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/files.contribution.ts similarity index 76% rename from src/vs/workbench/contrib/files/electron-browser/files.contribution.ts rename to src/vs/workbench/contrib/files/electron-sandbox/files.contribution.ts index 737eeea2d5c..3f6524d0f64 100644 --- a/src/vs/workbench/contrib/files/electron-browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/files.contribution.ts @@ -3,17 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as os from 'os'; -import * as fs from 'fs'; import * as nls from 'vs/nls'; -import { join } from 'vs/base/common/path'; import { Registry } from 'vs/platform/registry/common/platform'; import { EditorInput } from 'vs/workbench/common/editor'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; -import { NativeTextFileEditor } from 'vs/workbench/contrib/files/electron-browser/textFileEditor'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { NativeTextFileEditor } from 'vs/workbench/contrib/files/electron-sandbox/textFileEditor'; // Register file editor Registry.as(EditorExtensions.Editors).registerEditor( @@ -26,8 +22,3 @@ Registry.as(EditorExtensions.Editors).registerEditor( new SyncDescriptor(FileEditorInput) ] ); - -// Register mkdtemp command -CommandsRegistry.registerCommand('mkdtemp', function () { - return fs.promises.mkdtemp(join(os.tmpdir(), 'vscodetmp-')); -}); diff --git a/src/vs/workbench/contrib/files/electron-browser/textFileEditor.ts b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts similarity index 94% rename from src/vs/workbench/contrib/files/electron-browser/textFileEditor.ts rename to src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts index 4ea06a47056..b5e50bd3c54 100644 --- a/src/vs/workbench/contrib/files/electron-browser/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts @@ -7,8 +7,7 @@ import * as nls from 'vs/nls'; import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; import { EditorOptions } from 'vs/workbench/common/editor'; -import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; -import { MIN_MAX_MEMORY_SIZE_MB, FALLBACK_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/node/files'; +import { FileOperationError, FileOperationResult, IFileService, MIN_MAX_MEMORY_SIZE_MB, FALLBACK_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files'; import { createErrorWithActions } from 'vs/base/common/errorsWithActions'; import { Action } from 'vs/base/common/actions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -23,7 +22,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { IExplorerService } from 'vs/workbench/contrib/files/common/files'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; /** diff --git a/src/vs/workbench/contrib/issue/electron-browser/issue.contribution.ts b/src/vs/workbench/contrib/issue/electron-browser/issue.contribution.ts index 542cfb5d5dc..8a206ec3501 100644 --- a/src/vs/workbench/contrib/issue/electron-browser/issue.contribution.ts +++ b/src/vs/workbench/contrib/issue/electron-browser/issue.contribution.ts @@ -13,7 +13,8 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue'; import { WorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issueService'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { IIssueService, IssueReporterData } from 'vs/platform/issue/node/issue'; +import { IssueReporterData } from 'vs/platform/issue/common/issue'; +import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue'; import { OpenIssueReporterArgs, OpenIssueReporterActionId } from 'vs/workbench/contrib/issue/common/commands'; const helpCategory = { value: nls.localize('help', "Help"), original: 'Help' }; diff --git a/src/vs/workbench/contrib/issue/electron-browser/issue.ts b/src/vs/workbench/contrib/issue/electron-browser/issue.ts index da0a15a4e64..fc6d4b70552 100644 --- a/src/vs/workbench/contrib/issue/electron-browser/issue.ts +++ b/src/vs/workbench/contrib/issue/electron-browser/issue.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IssueReporterData } from 'vs/platform/issue/node/issue'; +import { IssueReporterData } from 'vs/platform/issue/common/issue'; export const IWorkbenchIssueService = createDecorator('workbenchIssueService'); diff --git a/src/vs/workbench/contrib/issue/electron-browser/issueActions.ts b/src/vs/workbench/contrib/issue/electron-browser/issueActions.ts index 4b6b25c31c0..4eaaf7c3029 100644 --- a/src/vs/workbench/contrib/issue/electron-browser/issueActions.ts +++ b/src/vs/workbench/contrib/issue/electron-browser/issueActions.ts @@ -5,7 +5,7 @@ import { Action } from 'vs/base/common/actions'; import * as nls from 'vs/nls'; -import { IssueType } from 'vs/platform/issue/node/issue'; +import { IssueType } from 'vs/platform/issue/common/issue'; import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue'; export class OpenProcessExplorer extends Action { diff --git a/src/vs/workbench/contrib/issue/electron-browser/issueService.ts b/src/vs/workbench/contrib/issue/electron-browser/issueService.ts index 3efe946f1ee..2aa3029feef 100644 --- a/src/vs/workbench/contrib/issue/electron-browser/issueService.ts +++ b/src/vs/workbench/contrib/issue/electron-browser/issueService.ts @@ -3,13 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IssueReporterStyles, IIssueService, IssueReporterData, ProcessExplorerData, IssueReporterExtensionData } from 'vs/platform/issue/node/issue'; +import { IssueReporterStyles, IssueReporterData, ProcessExplorerData, IssueReporterExtensionData } from 'vs/platform/issue/common/issue'; +import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue'; import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, editorBackground, editorForeground, listHoverBackground, listHoverForeground, listHighlightForeground, textLinkActiveForeground, inputValidationErrorBackground, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; -import { webFrame } from 'electron'; +import { webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { assign } from 'vs/base/common/objects'; import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; diff --git a/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts b/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts index 97c16d4d4af..3109475f950 100644 --- a/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts +++ b/src/vs/workbench/contrib/logs/electron-browser/logsActions.ts @@ -7,7 +7,7 @@ import { Action } from 'vs/base/common/actions'; import { join } from 'vs/base/common/path'; import { URI } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IFileService } from 'vs/platform/files/common/files'; diff --git a/src/vs/workbench/contrib/markers/browser/media/markers.css b/src/vs/workbench/contrib/markers/browser/media/markers.css index 6ccf3e40f3a..b5570494b91 100644 --- a/src/vs/workbench/contrib/markers/browser/media/markers.css +++ b/src/vs/workbench/contrib/markers/browser/media/markers.css @@ -22,7 +22,6 @@ .monaco-workbench.vs .monaco-action-bar .markers-panel-action-filter .monaco-inputbox { height: 25px; - border: 1px solid transparent; } .markers-panel-action-filter > .markers-panel-filter-controls { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 69d0a1ad357..b997ba59d80 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -469,10 +469,10 @@ export async function changeCellToKind(kind: CellKind, context: INotebookCellAct } export interface INotebookCellActionContext { - cellTemplate?: BaseCellRenderTemplate; - cell: ICellViewModel; - notebookEditor: INotebookEditor; - ui?: boolean; + readonly cellTemplate?: BaseCellRenderTemplate; + readonly cell: ICellViewModel; + readonly notebookEditor: INotebookEditor; + readonly ui?: boolean; } abstract class InsertCellCommand extends NotebookAction { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index f090abdede6..8ff3f971dc7 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -359,11 +359,10 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR } renderTemplate(container: HTMLElement): MarkdownCellRenderTemplate { - const contextKeyService = this.contextKeyServiceProvider(container); - container.tabIndex = -1; container.classList.add('markdown-cell-row'); const disposables = new DisposableStore(); + const contextKeyService = disposables.add(this.contextKeyServiceProvider(container)); const toolbar = disposables.add(this.createToolbar(container)); const focusIndicator = DOM.append(container, DOM.$('.notebook-cell-focus-indicator')); focusIndicator.setAttribute('draggable', 'true'); @@ -897,11 +896,10 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende } renderTemplate(container: HTMLElement): CodeCellRenderTemplate { - const contextKeyService = this.contextKeyServiceProvider(container); - container.classList.add('code-cell-row'); container.tabIndex = -1; const disposables = new DisposableStore(); + const contextKeyService = disposables.add(this.contextKeyServiceProvider(container)); const toolbar = disposables.add(this.createToolbar(container)); const focusIndicator = DOM.append(container, DOM.$('.notebook-cell-focus-indicator')); focusIndicator.setAttribute('draggable', 'true'); @@ -914,7 +912,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende const executionOrderLabel = DOM.append(runButtonContainer, $('div.execution-count-label')); // create a special context key service that set the inCompositeEditor-contextkey - const editorContextKeyService = this.contextKeyServiceProvider(container); + const editorContextKeyService = disposables.add(this.contextKeyServiceProvider(container)); const editorInstaService = this.instantiationService.createChild(new ServiceCollection([IContextKeyService, editorContextKeyService])); EditorContextKeys.inCompositeEditor.bindTo(editorContextKeyService).set(true); diff --git a/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts b/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts index 22caa9f65cf..27297f24966 100644 --- a/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts +++ b/src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts @@ -18,7 +18,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { URI } from 'vs/base/common/uri'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { IProductService } from 'vs/platform/product/common/productService'; export class StartupProfiler implements IWorkbenchContribution { diff --git a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts index 56f1145ba71..4943b79c0dd 100644 --- a/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts +++ b/src/vs/workbench/contrib/performance/electron-browser/startupTimings.ts @@ -14,7 +14,7 @@ import { ILifecycleService, StartupKind, StartupKindToString } from 'vs/platform import product from 'vs/platform/product/common/product'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUpdateService } from 'vs/platform/update/common/update'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import * as files from 'vs/workbench/contrib/files/common/files'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; diff --git a/src/vs/workbench/contrib/preferences/browser/tocTree.ts b/src/vs/workbench/contrib/preferences/browser/tocTree.ts index 70189937d1c..b8bc079ae71 100644 --- a/src/vs/workbench/contrib/preferences/browser/tocTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/tocTree.ts @@ -157,7 +157,11 @@ export function createTOCIterator(model: TOCTreeModel | SettingsTreeGroupElement class SettingsAccessibilityProvider implements IListAccessibilityProvider { getWidgetAriaLabel(): string { - return localize('settingsTOC', "Settings Table of Contents"); + return localize({ + key: 'settingsTOC', + comment: ['A label for the table of contents for the full settings list'] + }, + "Settings Table of Contents"); } getAriaLabel(element: SettingsTreeElement): string { diff --git a/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts b/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts index bed450069dc..bf829f2aaed 100644 --- a/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts +++ b/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts @@ -21,7 +21,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { DialogChannel } from 'vs/platform/dialogs/electron-browser/dialogIpc'; import { DownloadServiceChannel } from 'vs/platform/download/common/downloadIpc'; import { LoggerChannel } from 'vs/platform/log/common/logIpc'; -import { ipcRenderer as ipc } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { IDiagnosticInfoOptions, IRemoteDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { PersistentConnectionEventType } from 'vs/platform/remote/common/remoteAgentConnection'; @@ -55,7 +55,7 @@ class RemoteAgentDiagnosticListener implements IWorkbenchContribution { @IRemoteAgentService remoteAgentService: IRemoteAgentService, @ILabelService labelService: ILabelService ) { - ipc.on('vscode:getDiagnosticInfo', (event: Event, request: { replyChannel: string, args: IDiagnosticInfoOptions }): void => { + ipcRenderer.on('vscode:getDiagnosticInfo', (event: unknown, request: { replyChannel: string, args: IDiagnosticInfoOptions }): void => { const connection = remoteAgentService.getConnection(); if (connection) { const hostName = labelService.getHostLabel(REMOTE_HOST_SCHEME, connection.remoteAuthority); @@ -65,14 +65,14 @@ class RemoteAgentDiagnosticListener implements IWorkbenchContribution { (info as IRemoteDiagnosticInfo).hostName = hostName; } - ipc.send(request.replyChannel, info); + ipcRenderer.send(request.replyChannel, info); }) .catch(e => { const errorMessage = e && e.message ? `Fetching remote diagnostics for '${hostName}' failed: ${e.message}` : `Fetching remote diagnostics for '${hostName}' failed.`; - ipc.send(request.replyChannel, { hostName, errorMessage }); + ipcRenderer.send(request.replyChannel, { hostName, errorMessage }); }); } else { - ipc.send(request.replyChannel); + ipcRenderer.send(request.replyChannel); } }); } diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPane.ts b/src/vs/workbench/contrib/scm/browser/repositoryPane.ts index 92c78aa28a2..e68afdfbdfe 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPane.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPane.ts @@ -89,13 +89,18 @@ function splitMatches(uri: URI, filterData: FuzzyScore | undefined): [IMatch[] | const allMatches = createMatches(filterData); for (const match of allMatches) { - if (match.end <= fileName.length) { - matches!.push(match); + if (match.start < fileName.length) { + matches!.push( + { + start: match.start, + end: Math.min(match.end, fileName.length) + } + ); } else { descriptionMatches!.push( { - start: match.start - fileName.length, - end: match.end - fileName.length + start: match.start - (fileName.length + 1), + end: match.end - (fileName.length + 1) } ); } @@ -403,7 +408,7 @@ export class SCMTreeKeyboardNavigationLabelProvider implements ICompressibleKeyb const fileName = basename(element.sourceUri); const filePath = this.labelService.getUriLabel(dirname(element.sourceUri), { relative: true }); - return filePath.length !== 0 ? `${fileName}${filePath}` : fileName; + return filePath.length !== 0 ? `${fileName} ${filePath}` : fileName; } } diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 2ffee859696..468d6fe451c 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -869,7 +869,9 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { + this._register(this.searchInputFocusTracker.onDidFocus(async () => { this.searchInputBoxFocused.set(true); const useGlobalFindBuffer = this.searchConfiguration.globalFindClipboard; if (!this.ignoreGlobalFindBufferOnNextFocus && useGlobalFindBuffer) { - const globalBufferText = this.clipboardServce.readFindText(); + const globalBufferText = await this.clipboardServce.readFindText(); if (this.previousGlobalFindBufferValue !== globalBufferText) { this.searchInput.inputBox.addToHistory(); this.searchInput.setValue(globalBufferText); @@ -614,7 +614,7 @@ export class SearchWidget extends Widget { } } - private submitSearch(triggeredOnType = false, delay: number = 0): void { + private async submitSearch(triggeredOnType = false, delay: number = 0): Promise { this.searchInput.validate(); if (!this.searchInput.inputBox.isInputValid()) { return; @@ -623,7 +623,7 @@ export class SearchWidget extends Widget { const value = this.searchInput.getValue(); const useGlobalFindBuffer = this.searchConfiguration.globalFindClipboard; if (value && useGlobalFindBuffer) { - this.clipboardServce.writeFindText(value); + await this.clipboardServce.writeFindText(value); } this._onSearchSubmit.fire({ triggeredOnType, delay }); } diff --git a/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts b/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts index 6c197f94cac..836225138b1 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippets.contribution.ts @@ -28,7 +28,7 @@ const languageScopeSchemaId = 'vscode://schemas/snippets'; const snippetSchemaProperties: IJSONSchemaMap = { prefix: { - description: nls.localize('snippetSchema.json.prefix', 'The prefix to used when selecting the snippet in intellisense'), + description: nls.localize('snippetSchema.json.prefix', 'The prefix to use when selecting the snippet in intellisense'), type: ['string', 'array'] }, body: { diff --git a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts index 8fe4ddd1fc2..8bf519fd308 100644 --- a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts +++ b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ipcRenderer as ipc } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { join } from 'vs/base/common/path'; import { onDidChangeFullscreen, isFullscreen } from 'vs/base/browser/browser'; import { getTotalHeight, getTotalWidth } from 'vs/base/browser/dom'; @@ -26,6 +26,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import * as perf from 'vs/base/common/performance'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { assertIsDefined } from 'vs/base/common/types'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; class PartsSplash { @@ -45,6 +46,7 @@ class PartsSplash { @ILifecycleService lifecycleService: ILifecycleService, @IEditorGroupsService editorGroupsService: IEditorGroupsService, @IConfigurationService configService: IConfigurationService, + @IElectronService private readonly _electronService: IElectronService ) { lifecycleService.when(LifecyclePhase.Restored).then(_ => { this._removePartsSplash(); @@ -112,7 +114,7 @@ class PartsSplash { // the color needs to be in hex const backgroundColor = this._themeService.getColorTheme().getColor(editorBackground) || themes.WORKBENCH_BACKGROUND(this._themeService.getColorTheme()); const payload = JSON.stringify({ baseTheme, background: Color.Format.CSS.formatHex(backgroundColor) }); - ipc.send('vscode:changeColorTheme', this._envService.configuration.windowId, payload); + ipcRenderer.send('vscode:changeColorTheme', this._electronService.windowId, payload); } } diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index 34777c0470d..1f00527bd18 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -821,7 +821,6 @@ export class TerminalTaskSystem implements ITaskSystem { }); promise = new Promise((resolve, reject) => { const onExit = terminal!.onExit((exitCode) => { - onData.dispose(); onExit.dispose(); let key = task.getMapKey(); this.removeFromActiveTasks(task); @@ -847,8 +846,12 @@ export class TerminalTaskSystem implements ITaskSystem { this.terminalService.setActiveInstance(terminal); this.terminalService.showPanel(false); } - startStopProblemMatcher.done(); - startStopProblemMatcher.dispose(); + // Hack to work around #92868 until terminal is fixed. + setTimeout(() => { + onData.dispose(); + startStopProblemMatcher.done(); + startStopProblemMatcher.dispose(); + }, 100); if (!processStartedSignaled && terminal) { this._onDidStateChange.fire(TaskEvent.create(TaskEventKind.ProcessStarted, task, terminal.processId!)); processStartedSignaled = true; @@ -1040,7 +1043,7 @@ export class TerminalTaskSystem implements ITaskSystem { } } // This must be normalized to the OS - shellLaunchConfig.cwd = resources.toLocalResource(URI.from({ scheme: Schemas.file, path: cwd }), this.environmentService.configuration.remoteAuthority); + shellLaunchConfig.cwd = isUNC(cwd) ? cwd : resources.toLocalResource(URI.from({ scheme: Schemas.file, path: cwd }), this.environmentService.configuration.remoteAuthority); } if (options.env) { shellLaunchConfig.env = options.env; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index dfaef3ea7e4..330f1227a89 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -26,7 +26,7 @@ import { URI } from 'vs/base/common/uri'; import { isWindows } from 'vs/base/common/platform'; import { withNullAsUndefined } from 'vs/base/common/types'; import { ITerminalInstance, ITerminalService, Direction } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; +import { Action2, registerAction2, ILocalizedString } from 'vs/platform/actions/common/actions'; import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; import { ToggleViewAction } from 'vs/workbench/browser/actions/layoutActions'; import { IViewsService, IViewDescriptorService } from 'vs/workbench/common/views'; @@ -393,13 +393,13 @@ export class ClearTerminalAction extends Action { } export function registerTerminalActions() { - const category = TERMINAL_ACTION_CATEGORY; + const category: ILocalizedString = { value: TERMINAL_ACTION_CATEGORY, original: 'Terminal' }; registerAction2(class extends Action2 { constructor() { super({ id: TERMINAL_COMMAND_ID.NEW_IN_ACTIVE_WORKSPACE, - title: localize('workbench.action.terminal.newInActiveWorkspace', "Create New Integrated Terminal (In Active Workspace)"), + title: { value: localize('workbench.action.terminal.newInActiveWorkspace', "Create New Integrated Terminal (In Active Workspace)"), original: 'Create New Integrated Terminal (In Active Workspace)' }, f1: true, category }); @@ -418,7 +418,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FOCUS_PREVIOUS_PANE, - title: localize('workbench.action.terminal.focusPreviousPane', "Focus Previous Pane"), + title: { value: localize('workbench.action.terminal.focusPreviousPane', "Focus Previous Pane"), original: 'Focus Previous Pane' }, f1: true, category, keybinding: { @@ -443,7 +443,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FOCUS_NEXT_PANE, - title: localize('workbench.action.terminal.focusNextPane', "Focus Next Pane"), + title: { value: localize('workbench.action.terminal.focusNextPane', "Focus Next Pane"), original: 'Focus Next Pane' }, f1: true, category, keybinding: { @@ -468,7 +468,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RESIZE_PANE_LEFT, - title: localize('workbench.action.terminal.resizePaneLeft', "Resize Pane Left"), + title: { value: localize('workbench.action.terminal.resizePaneLeft', "Resize Pane Left"), original: 'Resize Pane Left' }, f1: true, category, keybinding: { @@ -487,7 +487,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RESIZE_PANE_RIGHT, - title: localize('workbench.action.terminal.resizePaneRight', "Resize Pane Right"), + title: { value: localize('workbench.action.terminal.resizePaneRight', "Resize Pane Right"), original: 'Resize Pane Right' }, f1: true, category, keybinding: { @@ -506,7 +506,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RESIZE_PANE_UP, - title: localize('workbench.action.terminal.resizePaneUp', "Resize Pane Up"), + title: { value: localize('workbench.action.terminal.resizePaneUp', "Resize Pane Up"), original: 'Resize Pane Up' }, f1: true, category, keybinding: { @@ -524,7 +524,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RESIZE_PANE_DOWN, - title: localize('workbench.action.terminal.resizePaneDown', "Resize Pane Down"), + title: { value: localize('workbench.action.terminal.resizePaneDown', "Resize Pane Down"), original: 'Resize Pane Down' }, f1: true, category, keybinding: { @@ -542,7 +542,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FOCUS, - title: localize('workbench.action.terminal.focus', "Focus Terminal"), + title: { value: localize('workbench.action.terminal.focus', "Focus Terminal"), original: 'Focus Terminal' }, f1: true, category }); @@ -561,7 +561,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FOCUS_NEXT, - title: localize('workbench.action.terminal.focusNext', "Focus Next Terminal"), + title: { value: localize('workbench.action.terminal.focusNext', "Focus Next Terminal"), original: 'Focus Next Terminal' }, f1: true, category }); @@ -576,7 +576,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FOCUS_PREVIOUS, - title: localize('workbench.action.terminal.focusPrevious', "Focus Previous Terminal"), + title: { value: localize('workbench.action.terminal.focusPrevious', "Focus Previous Terminal"), original: 'Focus Previous Terminal' }, f1: true, category }); @@ -591,7 +591,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RUN_SELECTED_TEXT, - title: localize('workbench.action.terminal.runSelectedText', "Run Selected Text In Active Terminal"), + title: { value: localize('workbench.action.terminal.runSelectedText', "Run Selected Text In Active Terminal"), original: 'Run Selected Text In Active Terminal' }, f1: true, category }); @@ -621,7 +621,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RUN_ACTIVE_FILE, - title: localize('workbench.action.terminal.runActiveFile', "Run Active File In Active Terminal"), + title: { value: localize('workbench.action.terminal.runActiveFile', "Run Active File In Active Terminal"), original: 'Run Active File In Active Terminal' }, f1: true, category }); @@ -655,7 +655,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_DOWN_LINE, - title: localize('workbench.action.terminal.scrollDown', "Scroll Down (Line)"), + title: { value: localize('workbench.action.terminal.scrollDown', "Scroll Down (Line)"), original: 'Scroll Down (Line)' }, f1: true, category, keybinding: { @@ -674,7 +674,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_DOWN_PAGE, - title: localize('workbench.action.terminal.scrollDownPage', "Scroll Down (Page)"), + title: { value: localize('workbench.action.terminal.scrollDownPage', "Scroll Down (Page)"), original: 'Scroll Down (Page)' }, f1: true, category, keybinding: { @@ -693,7 +693,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_TO_BOTTOM, - title: localize('workbench.action.terminal.scrollToBottom', "Scroll to Bottom"), + title: { value: localize('workbench.action.terminal.scrollToBottom', "Scroll to Bottom"), original: 'Scroll to Bottom' }, f1: true, category, keybinding: { @@ -712,7 +712,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_UP_LINE, - title: localize('workbench.action.terminal.scrollUp', "Scroll Up (Line)"), + title: { value: localize('workbench.action.terminal.scrollUp', "Scroll Up (Line)"), original: 'Scroll Up (Line)' }, f1: true, category, keybinding: { @@ -731,7 +731,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_UP_PAGE, - title: localize('workbench.action.terminal.scrollUpPage', "Scroll Up (Page)"), + title: { value: localize('workbench.action.terminal.scrollUpPage', "Scroll Up (Page)"), original: 'Scroll Up (Page)' }, f1: true, category, keybinding: { @@ -750,7 +750,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_TO_TOP, - title: localize('workbench.action.terminal.scrollToTop', "Scroll to Top"), + title: { value: localize('workbench.action.terminal.scrollToTop', "Scroll to Top"), original: 'Scroll to Top' }, f1: true, category, keybinding: { @@ -769,7 +769,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_EXIT, - title: localize('workbench.action.terminal.navigationModeExit', "Exit Navigation Mode"), + title: { value: localize('workbench.action.terminal.navigationModeExit', "Exit Navigation Mode"), original: 'Exit Navigation Mode' }, f1: true, category, keybinding: { @@ -787,7 +787,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_PREVIOUS, - title: localize('workbench.action.terminal.navigationModeFocusPrevious', "Focus Previous Line (Navigation Mode)"), + title: { value: localize('workbench.action.terminal.navigationModeFocusPrevious', "Focus Previous Line (Navigation Mode)"), original: 'Focus Previous Line (Navigation Mode)' }, f1: true, category, keybinding: { @@ -808,7 +808,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_NEXT, - title: localize('workbench.action.terminal.navigationModeFocusNext', "Focus Next Line (Navigation Mode)"), + title: { value: localize('workbench.action.terminal.navigationModeFocusNext', "Focus Next Line (Navigation Mode)"), original: 'Focus Next Line (Navigation Mode)' }, f1: true, category, keybinding: { @@ -829,7 +829,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.CLEAR_SELECTION, - title: localize('workbench.action.terminal.clearSelection', "Clear Selection"), + title: { value: localize('workbench.action.terminal.clearSelection', "Clear Selection"), original: 'Clear Selection' }, f1: true, category, keybinding: { @@ -850,7 +850,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.MANAGE_WORKSPACE_SHELL_PERMISSIONS, - title: localize('workbench.action.terminal.manageWorkspaceShellPermissions', "Manage Workspace Shell Permissions"), + title: { value: localize('workbench.action.terminal.manageWorkspaceShellPermissions', "Manage Workspace Shell Permissions"), original: 'Manage Workspace Shell Permissions' }, f1: true, category }); @@ -863,7 +863,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RENAME, - title: localize('workbench.action.terminal.rename', "Rename"), + title: { value: localize('workbench.action.terminal.rename', "Rename"), original: 'Rename' }, f1: true, category }); @@ -884,7 +884,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FIND_FOCUS, - title: localize('workbench.action.terminal.focusFind', "Focus Find"), + title: { value: localize('workbench.action.terminal.focusFind', "Focus Find"), original: 'Focus Find' }, f1: true, category, keybinding: { @@ -902,7 +902,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FIND_HIDE, - title: localize('workbench.action.terminal.hideFind', "Hide Find"), + title: { value: localize('workbench.action.terminal.hideFind', "Hide Find"), original: 'Hide Find' }, f1: true, category, keybinding: { @@ -921,7 +921,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.QUICK_OPEN_TERM, - title: localize('quickAccessTerminal', "Switch Active Terminal"), + title: { value: localize('quickAccessTerminal', "Switch Active Terminal"), original: 'Switch Active Terminal' }, f1: true, category }); @@ -934,7 +934,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_TO_PREVIOUS_COMMAND, - title: localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"), + title: { value: localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"), original: 'Scroll To Previous Command' }, f1: true, category, keybinding: { @@ -955,7 +955,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SCROLL_TO_NEXT_COMMAND, - title: localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"), + title: { value: localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"), original: 'Scroll To Next Command' }, f1: true, category, keybinding: { @@ -976,7 +976,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_COMMAND, - title: localize('workbench.action.terminal.selectToPreviousCommand', "Select To Previous Command"), + title: { value: localize('workbench.action.terminal.selectToPreviousCommand', "Select To Previous Command"), original: 'Select To Previous Command' }, f1: true, category, keybinding: { @@ -997,7 +997,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SELECT_TO_NEXT_COMMAND, - title: localize('workbench.action.terminal.selectToNextCommand', "Select To Next Command"), + title: { value: localize('workbench.action.terminal.selectToNextCommand', "Select To Next Command"), original: 'Select To Next Command' }, f1: true, category, keybinding: { @@ -1018,7 +1018,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_LINE, - title: localize('workbench.action.terminal.selectToPreviousLine', "Select To Previous Line"), + title: { value: localize('workbench.action.terminal.selectToPreviousLine', "Select To Previous Line"), original: 'Select To Previous Line' }, f1: true, category }); @@ -1034,7 +1034,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SELECT_TO_NEXT_LINE, - title: localize('workbench.action.terminal.selectToNextLine', "Select To Next Line"), + title: { value: localize('workbench.action.terminal.selectToNextLine', "Select To Next Line"), original: 'Select To Next Line' }, f1: true, category }); @@ -1050,7 +1050,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.TOGGLE_ESCAPE_SEQUENCE_LOGGING, - title: localize('workbench.action.terminal.toggleEscapeSequenceLogging', "Toggle Escape Sequence Logging"), + title: { value: localize('workbench.action.terminal.toggleEscapeSequenceLogging', "Toggle Escape Sequence Logging"), original: 'Toggle Escape Sequence Logging' }, f1: true, category }); @@ -1064,7 +1064,7 @@ export function registerTerminalActions() { const title = localize('workbench.action.terminal.sendSequence', "Send Custom Sequence To Terminal"); super({ id: TERMINAL_COMMAND_ID.SEND_SEQUENCE, - title, + title: { value: title, original: 'Send Custom Sequence To Terminal' }, category, description: { description: title, @@ -1090,7 +1090,7 @@ export function registerTerminalActions() { const title = localize('workbench.action.terminal.newWithCwd', "Create New Integrated Terminal Starting in a Custom Working Directory"); super({ id: TERMINAL_COMMAND_ID.NEW_WITH_CWD, - title, + title: { value: title, original: 'Create New Integrated Terminal Starting in a Custom Working Directory' }, category, description: { description: title, @@ -1125,7 +1125,7 @@ export function registerTerminalActions() { const title = localize('workbench.action.terminal.renameWithArg', "Rename the Currently Active Terminal"); super({ id: TERMINAL_COMMAND_ID.RENAME_WITH_ARG, - title, + title: { value: title, original: 'Rename the Currently Active Terminal' }, category, description: { description: title, @@ -1159,7 +1159,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX, - title: localize('workbench.action.terminal.toggleFindRegex', "Toggle Find Using Regex"), + title: { value: localize('workbench.action.terminal.toggleFindRegex', "Toggle Find Using Regex"), original: 'Toggle Find Using Regex' }, f1: true, category, keybinding: { @@ -1179,7 +1179,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD, - title: localize('workbench.action.terminal.toggleFindWholeWord', "Toggle Find Using Whole Word"), + title: { value: localize('workbench.action.terminal.toggleFindWholeWord', "Toggle Find Using Whole Word"), original: 'Toggle Find Using Whole Word' }, f1: true, category, keybinding: { @@ -1199,7 +1199,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE, - title: localize('workbench.action.terminal.toggleFindCaseSensitive', "Toggle Find Using Case Sensitive"), + title: { value: localize('workbench.action.terminal.toggleFindCaseSensitive', "Toggle Find Using Case Sensitive"), original: 'Toggle Find Using Case Sensitive' }, f1: true, category, keybinding: { @@ -1219,7 +1219,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FIND_NEXT, - title: localize('workbench.action.terminal.findNext', "Find Next"), + title: { value: localize('workbench.action.terminal.findNext', "Find Next"), original: 'Find Next' }, f1: true, category, keybinding: [ @@ -1245,7 +1245,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.FIND_PREVIOUS, - title: localize('workbench.action.terminal.findPrevious', "Find Previous"), + title: { value: localize('workbench.action.terminal.findPrevious', "Find Previous"), original: 'Find Previous' }, f1: true, category, keybinding: [ @@ -1271,7 +1271,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.RELAUNCH, - title: localize('workbench.action.terminal.relaunch', "Relaunch Active Terminal"), + title: { value: localize('workbench.action.terminal.relaunch', "Relaunch Active Terminal"), original: 'Relaunch Active Terminal' }, f1: true, category }); @@ -1284,7 +1284,7 @@ export function registerTerminalActions() { constructor() { super({ id: TERMINAL_COMMAND_ID.SHOW_ENVIRONMENT_INFORMATION, - title: localize('workbench.action.terminal.showEnvironmentInformation', "Show Environment Information"), + title: { value: localize('workbench.action.terminal.showEnvironmentInformation', "Show Environment Information"), original: 'Show Environment Information' }, f1: true, category }); diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index f369566829c..91a5f251a3a 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -16,17 +16,26 @@ export const terminalConfiguration: IConfigurationNode = { type: 'object', properties: { 'terminal.integrated.automationShell.linux': { - markdownDescription: localize('terminal.integrated.automationShell.linux', "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.linux`', '`shellArgs`'), + markdownDescription: localize({ + key: 'terminal.integrated.automationShell.linux', + comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys'] + }, "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.linux`', '`shellArgs`'), type: ['string', 'null'], default: null }, 'terminal.integrated.automationShell.osx': { - markdownDescription: localize('terminal.integrated.automationShell.osx', "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.osx`', '`shellArgs`'), + markdownDescription: localize({ + key: 'terminal.integrated.automationShell.osx', + comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys'] + }, "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.osx`', '`shellArgs`'), type: ['string', 'null'], default: null }, 'terminal.integrated.automationShell.windows': { - markdownDescription: localize('terminal.integrated.automationShell.windows', "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.windows`', '`shellArgs`'), + markdownDescription: localize({ + key: 'terminal.integrated.automationShell.windows', + comment: ['{0} and {1} are the `shell` and `shellArgs` settings keys'] + }, "A path that when set will override {0} and ignore {1} values for automation-related terminal usage like tasks and debug.", '`terminal.integrated.shell.windows`', '`shellArgs`'), type: ['string', 'null'], default: null }, diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalNativeService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalNativeService.ts index cc02eddf1ea..43d9e84ec57 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalNativeService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalNativeService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ipcRenderer as ipc } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { IOpenFileRequest } from 'vs/platform/windows/common/windows'; import { ITerminalNativeService, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; import { URI } from 'vs/base/common/uri'; @@ -31,8 +31,8 @@ export class TerminalNativeService implements ITerminalNativeService { @IInstantiationService readonly instantiationService: IInstantiationService, @IRemoteAgentService remoteAgentService: IRemoteAgentService ) { - ipc.on('vscode:openFiles', (_event: any, request: IOpenFileRequest) => this._onOpenFileRequest.fire(request)); - ipc.on('vscode:osResume', () => this._onOsResume.fire()); + ipcRenderer.on('vscode:openFiles', (event: unknown, request: IOpenFileRequest) => this._onOpenFileRequest.fire(request)); + ipcRenderer.on('vscode:osResume', () => this._onOsResume.fire()); const connection = remoteAgentService.getConnection(); if (connection && connection.remoteAuthority) { diff --git a/src/vs/workbench/contrib/url/browser/trustedDomains.ts b/src/vs/workbench/contrib/url/browser/trustedDomains.ts index 48b63c75984..f6bd446b7bc 100644 --- a/src/vs/workbench/contrib/url/browser/trustedDomains.ts +++ b/src/vs/workbench/contrib/url/browser/trustedDomains.ts @@ -142,8 +142,8 @@ async function getRemotes(fileService: IFileService, textFileService: ITextFileS const RemoteMatcher = /^\s*url\s*=\s*(?:git@|https:\/\/)github\.com(?::|\/)([^.]*)\.git\s*$/mg; while (match = RemoteMatcher.exec(content)) { - const [domain, repo] = [match[1], match[2]]; - if (domain && repo) { + const repo = match[1]; + if (repo) { domains.add(`https://github.com/${repo}/`); } } diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 27f7095a451..23b661add1c 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -292,7 +292,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo this.disableSync(); this.notificationService.notify({ severity: Severity.Error, - message: localize('error upgrade required', "Turned off sync because the current version ({0}) of {1} is not compatible with the Preferences Sync Service. Please update and turn on sync to continue syncing.", this.productService.version, this.productService.nameLong), + message: localize('error upgrade required', "Turned off sync because the current version ({0}, {1}) of {2} is not compatible with the Preferences Sync Service. Please update and turn on sync to continue syncing.", this.productService.version, this.productService.commit, this.productService.nameLong), }); return true; } diff --git a/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts b/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts index 3fc43388f2b..5c7c757451f 100644 --- a/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts +++ b/src/vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution.ts @@ -14,7 +14,7 @@ import { localize } from 'vs/nls'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IFileService } from 'vs/platform/files/common/files'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { Action } from 'vs/base/common/actions'; import { IWorkbenchIssueService } from 'vs/workbench/contrib/issue/electron-browser/issue'; diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index bdffe18a853..dd9cf13f1ed 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { FindInPageOptions, OnBeforeRequestListenerDetails, OnHeadersReceivedListenerDetails, Response, WebContents, WebviewTag, ipcRenderer } from 'electron'; +import { FindInPageOptions, OnBeforeRequestListenerDetails, OnHeadersReceivedListenerDetails, Response, WebContents, WebviewTag } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { addDisposableListener } from 'vs/base/browser/dom'; import { ThrottledDelayer } from 'vs/base/common/async'; import { Emitter, Event } from 'vs/base/common/event'; diff --git a/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.contribution.ts similarity index 93% rename from src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution.ts rename to src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.contribution.ts index 44b1e266005..5c4f1ccf06e 100644 --- a/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.contribution.ts @@ -6,6 +6,6 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { NativeTelemetryOptOut } from 'vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut'; +import { NativeTelemetryOptOut } from 'vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut'; Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeTelemetryOptOut, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.ts similarity index 96% rename from src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.ts rename to src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.ts index d561cf83320..0adc911b514 100644 --- a/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.ts @@ -13,7 +13,7 @@ import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common import { IProductService } from 'vs/platform/product/common/productService'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { AbstractTelemetryOptOut } from 'vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; export class NativeTelemetryOptOut extends AbstractTelemetryOptOut { diff --git a/src/vs/workbench/electron-browser/actions/developerActions.ts b/src/vs/workbench/electron-browser/actions/developerActions.ts index e4c1160ca47..41520472442 100644 --- a/src/vs/workbench/electron-browser/actions/developerActions.ts +++ b/src/vs/workbench/electron-browser/actions/developerActions.ts @@ -5,28 +5,10 @@ import { Action } from 'vs/base/common/actions'; import * as nls from 'vs/nls'; -import { IElectronService } from 'vs/platform/electron/node/electron'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; -import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; - -export class ToggleDevToolsAction extends Action { - - static readonly ID = 'workbench.action.toggleDevTools'; - static readonly LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools"); - - constructor( - id: string, - label: string, - @IElectronService private readonly electronService: IElectronService - ) { - super(id, label); - } - - run(): Promise { - return this.electronService.toggleDevTools(); - } -} +import { Registry } from 'vs/platform/registry/common/platform'; +import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; export class ToggleSharedProcessAction extends Action { @@ -46,21 +28,7 @@ export class ToggleSharedProcessAction extends Action { } } -export class ConfigureRuntimeArgumentsAction extends Action { +const registry = Registry.as(Extensions.WorkbenchActions); - static readonly ID = 'workbench.action.configureRuntimeArguments'; - static readonly LABEL = nls.localize('configureRuntimeArguments', "Configure Runtime Arguments"); - - constructor( - id: string, - label: string, - @IEnvironmentService private readonly environmentService: IEnvironmentService, - @IEditorService private readonly editorService: IEditorService - ) { - super(id, label); - } - - async run(): Promise { - await this.editorService.openEditor({ resource: this.environmentService.argvResource }); - } -} +const developerCategory = nls.localize('developer', "Developer"); +registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleSharedProcessAction), 'Developer: Toggle Shared Process', developerCategory); diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index ba9d01fbba8..e180d652ea9 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -5,7 +5,7 @@ import * as fs from 'fs'; import * as gracefulFs from 'graceful-fs'; -import { webFrame } from 'electron'; +import { webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { importEntries, mark } from 'vs/base/common/performance'; import { Workbench } from 'vs/workbench/browser/workbench'; import { NativeWindow } from 'vs/workbench/electron-browser/window'; @@ -30,7 +30,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IStorageService } from 'vs/platform/storage/common/storage'; import { Disposable } from 'vs/base/common/lifecycle'; import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver'; -import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; +import { IMainProcessService, MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { RemoteAuthorityResolverService } from 'vs/platform/remote/electron-browser/remoteAuthorityResolverService'; import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; @@ -49,6 +49,7 @@ import product from 'vs/platform/product/common/product'; import { NativeResourceIdentityService } from 'vs/platform/resource/node/resourceIdentityServiceImpl'; import { IResourceIdentityService } from 'vs/platform/resource/common/resourceIdentityService'; import { DesktopLogService } from 'vs/workbench/services/log/electron-browser/logService'; +import { IElectronService, ElectronService } from 'vs/platform/electron/electron-sandbox/electron'; class DesktopMain extends Disposable { @@ -191,14 +192,19 @@ class DesktopMain extends Disposable { const signService = new SignService(); serviceCollection.set(ISignService, signService); + // Remote Agent const remoteAgentService = this._register(new RemoteAgentService(this.environmentService, remoteAuthorityResolverService, signService, logService)); serviceCollection.set(IRemoteAgentService, remoteAgentService); + // Electron + const electronService = new ElectronService(this.configuration.windowId, mainProcessService) as IElectronService; + serviceCollection.set(IElectronService, electronService); + // Files const fileService = this._register(new FileService(logService)); serviceCollection.set(IFileService, fileService); - const diskFileSystemProvider = this._register(new DiskFileSystemProvider(logService)); + const diskFileSystemProvider = this._register(new DiskFileSystemProvider(logService, electronService)); fileService.registerProvider(Schemas.file, diskFileSystemProvider); // User Data Provider diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 545bf31888b..734d652d3a7 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -22,7 +22,8 @@ import * as browser from 'vs/base/browser/browser'; import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands'; import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { KeyboardMapperFactory } from 'vs/workbench/services/keybinding/electron-browser/nativeKeymapService'; -import { ipcRenderer as ipc, webFrame, crashReporter, CrashReporterStartOptions, Event as IpcEvent } from 'electron'; +import { CrashReporterStartOptions } from 'vs/base/parts/sandbox/common/electronTypes'; +import { crashReporter, ipcRenderer, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { IMenuService, MenuId, IMenu, MenuItemAction, ICommandAction, SubmenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -49,11 +50,12 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { IUpdateService } from 'vs/platform/update/common/update'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { IPreferencesService } from '../services/preferences/common/preferences'; -import { IMenubarService, IMenubarData, IMenubarMenu, IMenubarKeybinding, IMenubarMenuItemSubmenu, IMenubarMenuItemAction, MenubarMenuItem } from 'vs/platform/menubar/node/menubar'; +import { IMenubarData, IMenubarMenu, IMenubarKeybinding, IMenubarMenuItemSubmenu, IMenubarMenuItemAction, MenubarMenuItem } from 'vs/platform/menubar/common/menubar'; +import { IMenubarService } from 'vs/platform/menubar/electron-sandbox/menubar'; import { withNullAsUndefined, assertIsDefined } from 'vs/base/common/types'; import { IOpenerService, OpenOptions } from 'vs/platform/opener/common/opener'; import { Schemas } from 'vs/base/common/network'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { posix, dirname } from 'vs/base/common/path'; import { getBaseLabel } from 'vs/base/common/labels'; import { ITunnelService, extractLocalHostUriMetaDataForPortMapping } from 'vs/platform/remote/common/tunnel'; @@ -127,7 +129,7 @@ export class NativeWindow extends Disposable { }); // Support runAction event - ipc.on('vscode:runAction', async (event: IpcEvent, request: IRunActionInWindowRequest) => { + ipcRenderer.on('vscode:runAction', async (event: unknown, request: IRunActionInWindowRequest) => { const args: unknown[] = request.args || []; // If we run an action from the touchbar, we fill in the currently active resource @@ -158,47 +160,47 @@ export class NativeWindow extends Disposable { }); // Support runKeybinding event - ipc.on('vscode:runKeybinding', (event: IpcEvent, request: IRunKeybindingInWindowRequest) => { + ipcRenderer.on('vscode:runKeybinding', (event: unknown, request: IRunKeybindingInWindowRequest) => { if (document.activeElement) { this.keybindingService.dispatchByUserSettingsLabel(request.userSettingsLabel, document.activeElement); } }); // Error reporting from main - ipc.on('vscode:reportError', (event: IpcEvent, error: string) => { + ipcRenderer.on('vscode:reportError', (event: unknown, error: string) => { if (error) { errors.onUnexpectedError(JSON.parse(error)); } }); // Support openFiles event for existing and new files - ipc.on('vscode:openFiles', (event: IpcEvent, request: IOpenFileRequest) => this.onOpenFiles(request)); + ipcRenderer.on('vscode:openFiles', (event: unknown, request: IOpenFileRequest) => this.onOpenFiles(request)); // Support addFolders event if we have a workspace opened - ipc.on('vscode:addFolders', (event: IpcEvent, request: IAddFoldersRequest) => this.onAddFoldersRequest(request)); + ipcRenderer.on('vscode:addFolders', (event: unknown, request: IAddFoldersRequest) => this.onAddFoldersRequest(request)); // Message support - ipc.on('vscode:showInfoMessage', (event: IpcEvent, message: string) => { + ipcRenderer.on('vscode:showInfoMessage', (event: unknown, message: string) => { this.notificationService.info(message); }); - ipc.on('vscode:displayChanged', (event: IpcEvent) => { + ipcRenderer.on('vscode:displayChanged', () => { clearAllFontInfos(); }); // Fullscreen Events - ipc.on('vscode:enterFullScreen', async () => { + ipcRenderer.on('vscode:enterFullScreen', async () => { await this.lifecycleService.when(LifecyclePhase.Ready); browser.setFullscreen(true); }); - ipc.on('vscode:leaveFullScreen', async () => { + ipcRenderer.on('vscode:leaveFullScreen', async () => { await this.lifecycleService.when(LifecyclePhase.Ready); browser.setFullscreen(false); }); // High Contrast Events - ipc.on('vscode:enterHighContrast', async () => { + ipcRenderer.on('vscode:enterHighContrast', async () => { const windowConfig = this.configurationService.getValue('window'); if (windowConfig?.autoDetectHighContrast) { await this.lifecycleService.when(LifecyclePhase.Ready); @@ -206,7 +208,7 @@ export class NativeWindow extends Disposable { } }); - ipc.on('vscode:leaveHighContrast', async () => { + ipcRenderer.on('vscode:leaveHighContrast', async () => { const windowConfig = this.configurationService.getValue('window'); if (windowConfig?.autoDetectHighContrast) { await this.lifecycleService.when(LifecyclePhase.Ready); @@ -215,12 +217,12 @@ export class NativeWindow extends Disposable { }); // keyboard layout changed event - ipc.on('vscode:keyboardLayoutChanged', () => { + ipcRenderer.on('vscode:keyboardLayoutChanged', () => { KeyboardMapperFactory.INSTANCE._onKeyboardLayoutChanged(); }); // accessibility support changed event - ipc.on('vscode:accessibilitySupportChanged', (event: IpcEvent, accessibilitySupportEnabled: boolean) => { + ipcRenderer.on('vscode:accessibilitySupportChanged', (event: unknown, accessibilitySupportEnabled: boolean) => { this.accessibilityService.setAccessibilitySupport(accessibilitySupportEnabled ? AccessibilitySupport.Enabled : AccessibilitySupport.Disabled); }); @@ -284,8 +286,8 @@ export class NativeWindow extends Disposable { // Detect minimize / maximize this._register(Event.any( - Event.map(Event.filter(this.electronService.onWindowMaximize, id => id === this.environmentService.configuration.windowId), () => true), - Event.map(Event.filter(this.electronService.onWindowUnmaximize, id => id === this.environmentService.configuration.windowId), () => false) + Event.map(Event.filter(this.electronService.onWindowMaximize, id => id === this.electronService.windowId), () => true), + Event.map(Event.filter(this.electronService.onWindowUnmaximize, id => id === this.electronService.windowId), () => false) )(e => this.onDidChangeMaximized(e))); this.onDidChangeMaximized(this.environmentService.configuration.maximized ?? false); @@ -399,7 +401,7 @@ export class NativeWindow extends Disposable { this.setupOpenHandlers(); // Emit event when vscode is ready - this.lifecycleService.when(LifecyclePhase.Ready).then(() => ipc.send('vscode:workbenchReady', this.environmentService.configuration.windowId)); + this.lifecycleService.when(LifecyclePhase.Ready).then(() => ipcRenderer.send('vscode:workbenchReady', this.electronService.windowId)); // Integrity warning this.integrityService.isPure().then(res => this.titleService.updateProperties({ isPure: res.isPure })); @@ -430,16 +432,16 @@ export class NativeWindow extends Disposable { const companyName = product.crashReporter?.companyName || 'Microsoft'; const productName = product.crashReporter?.productName || product.nameShort; - // With appCenter enabled, crashes will be uploaded - if (product.appCenter) { - this.setupCrashReporter(companyName, productName, product.appCenter, undefined); - } - // With a provided crash reporter directory, crashes // will be stored only locally in that folder - else if (this.environmentService.crashReporterDirectory) { + if (this.environmentService.crashReporterDirectory) { this.setupCrashReporter(companyName, productName, undefined, this.environmentService.crashReporterDirectory); } + + // With appCenter enabled, crashes will be uploaded + else if (product.appCenter) { + this.setupCrashReporter(companyName, productName, product.appCenter, undefined); + } } } @@ -726,6 +728,7 @@ class NativeMenubarControl extends MenubarControl { @IAccessibilityService accessibilityService: IAccessibilityService, @IMenubarService private readonly menubarService: IMenubarService, @IHostService hostService: IHostService, + @IElectronService private readonly electronService: IElectronService ) { super( menuService, @@ -774,7 +777,7 @@ class NativeMenubarControl extends MenubarControl { // Send menus to main process to be rendered by Electron const menubarData = { menus: {}, keybindings: {} }; if (this.getMenubarMenus(menubarData)) { - this.menubarService.updateMenubar(this.environmentService.configuration.windowId, menubarData); + this.menubarService.updateMenubar(this.electronService.windowId, menubarData); } } diff --git a/src/vs/workbench/electron-sandbox/actions/developerActions.ts b/src/vs/workbench/electron-sandbox/actions/developerActions.ts new file mode 100644 index 00000000000..6c20467143d --- /dev/null +++ b/src/vs/workbench/electron-sandbox/actions/developerActions.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Action } from 'vs/base/common/actions'; +import * as nls from 'vs/nls'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; + +export class ToggleDevToolsAction extends Action { + + static readonly ID = 'workbench.action.toggleDevTools'; + static readonly LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools"); + + constructor( + id: string, + label: string, + @IElectronService private readonly electronService: IElectronService + ) { + super(id, label); + } + + run(): Promise { + return this.electronService.toggleDevTools(); + } +} + +export class ConfigureRuntimeArgumentsAction extends Action { + + static readonly ID = 'workbench.action.configureRuntimeArguments'; + static readonly LABEL = nls.localize('configureRuntimeArguments', "Configure Runtime Arguments"); + + constructor( + id: string, + label: string, + @IEnvironmentService private readonly environmentService: IEnvironmentService, + @IEditorService private readonly editorService: IEditorService + ) { + super(id, label); + } + + async run(): Promise { + await this.editorService.openEditor({ resource: this.environmentService.argvResource }); + } +} diff --git a/src/vs/workbench/electron-browser/actions/media/actions.css b/src/vs/workbench/electron-sandbox/actions/media/actions.css similarity index 100% rename from src/vs/workbench/electron-browser/actions/media/actions.css rename to src/vs/workbench/electron-sandbox/actions/media/actions.css diff --git a/src/vs/workbench/electron-browser/actions/windowActions.ts b/src/vs/workbench/electron-sandbox/actions/windowActions.ts similarity index 91% rename from src/vs/workbench/electron-browser/actions/windowActions.ts rename to src/vs/workbench/electron-sandbox/actions/windowActions.ts index 255a094fa06..e34b546a20b 100644 --- a/src/vs/workbench/electron-browser/actions/windowActions.ts +++ b/src/vs/workbench/electron-sandbox/actions/windowActions.ts @@ -10,7 +10,7 @@ import { Action } from 'vs/base/common/actions'; import * as nls from 'vs/nls'; import * as browser from 'vs/base/browser/browser'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { webFrame } from 'electron'; +import { webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { FileKind } from 'vs/platform/files/common/files'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -19,9 +19,7 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { ICommandHandler } from 'vs/platform/commands/common/commands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IElectronService } from 'vs/platform/electron/node/electron'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { Codicon } from 'vs/base/common/codicons'; export class CloseCurrentWindowAction extends Action { @@ -169,7 +167,6 @@ export abstract class BaseSwitchWindow extends Action { constructor( id: string, label: string, - private readonly environmentService: INativeWorkbenchEnvironmentService, private readonly quickInputService: IQuickInputService, private readonly keybindingService: IKeybindingService, private readonly modelService: IModelService, @@ -182,7 +179,7 @@ export abstract class BaseSwitchWindow extends Action { protected abstract isQuickNavigate(): boolean; async run(): Promise { - const currentWindowId = this.environmentService.configuration.windowId; + const currentWindowId = this.electronService.windowId; const windows = await this.electronService.getWindows(); const placeHolder = nls.localize('switchWindowPlaceHolder', "Select a window to switch to"); @@ -225,14 +222,13 @@ export class SwitchWindow extends BaseSwitchWindow { constructor( id: string, label: string, - @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService, @IQuickInputService quickInputService: IQuickInputService, @IKeybindingService keybindingService: IKeybindingService, @IModelService modelService: IModelService, @IModeService modeService: IModeService, @IElectronService electronService: IElectronService ) { - super(id, label, environmentService, quickInputService, keybindingService, modelService, modeService, electronService); + super(id, label, quickInputService, keybindingService, modelService, modeService, electronService); } protected isQuickNavigate(): boolean { @@ -248,14 +244,13 @@ export class QuickSwitchWindow extends BaseSwitchWindow { constructor( id: string, label: string, - @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService, @IQuickInputService quickInputService: IQuickInputService, @IKeybindingService keybindingService: IKeybindingService, @IModelService modelService: IModelService, @IModeService modeService: IModeService, @IElectronService electronService: IElectronService ) { - super(id, label, environmentService, quickInputService, keybindingService, modelService, modeService, electronService); + super(id, label, quickInputService, keybindingService, modelService, modeService, electronService); } protected isQuickNavigate(): boolean { diff --git a/src/vs/workbench/electron-browser/desktop.contribution.ts b/src/vs/workbench/electron-sandbox/desktop.contribution.ts similarity index 96% rename from src/vs/workbench/electron-browser/desktop.contribution.ts rename to src/vs/workbench/electron-sandbox/desktop.contribution.ts index 7739d40e638..98a5a69a614 100644 --- a/src/vs/workbench/electron-browser/desktop.contribution.ts +++ b/src/vs/workbench/electron-sandbox/desktop.contribution.ts @@ -5,21 +5,20 @@ import { Registry } from 'vs/platform/registry/common/platform'; import * as nls from 'vs/nls'; -import * as os from 'os'; import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform'; -import { ToggleSharedProcessAction, ToggleDevToolsAction, ConfigureRuntimeArgumentsAction } from 'vs/workbench/electron-browser/actions/developerActions'; -import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions'; +import { ToggleDevToolsAction, ConfigureRuntimeArgumentsAction } from 'vs/workbench/electron-sandbox/actions/developerActions'; +import { ZoomResetAction, ZoomOutAction, ZoomInAction, CloseCurrentWindowAction, SwitchWindow, QuickSwitchWindow, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-sandbox/actions/windowActions'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IsDevelopmentContext, IsMacContext } from 'vs/platform/contextkey/common/contextkeys'; import { NoEditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import product from 'vs/platform/product/common/product'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; @@ -91,7 +90,6 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; // Actions: Developer (function registerDeveloperActions(): void { const developerCategory = nls.localize('developer', "Developer"); - registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleSharedProcessAction), 'Developer: Toggle Shared Process', developerCategory); registry.registerWorkbenchAction(SyncActionDescriptor.from(ReloadWindowWithExtensionsDisabledAction), 'Developer: Reload With Extensions Disabled', developerCategory); registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleDevToolsAction), 'Developer: Toggle Developer Tools', developerCategory); @@ -282,7 +280,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; 'default': false, 'scope': ConfigurationScope.APPLICATION, 'description': nls.localize('window.nativeTabs', "Enables macOS Sierra window tabs. Note that changes require a full restart to apply and that native tabs will disable a custom title bar style if configured."), - 'included': isMacintosh && parseFloat(os.release()) >= 17 // Minimum: macOS Sierra (10.13.x = darwin 17.x) + 'included': isMacintosh }, 'window.nativeFullScreen': { 'type': 'boolean', diff --git a/src/vs/workbench/electron-browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts similarity index 99% rename from src/vs/workbench/electron-browser/parts/titlebar/titlebarPart.ts rename to src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts index 66a5283bd04..2753d07ac5b 100644 --- a/src/vs/workbench/electron-browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/electron-sandbox/parts/titlebar/titlebarPart.ts @@ -20,7 +20,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { getTitleBarStyle } from 'vs/platform/windows/common/windows'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Codicon } from 'vs/base/common/codicons'; diff --git a/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts b/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts index 623385c0a79..8e19430639c 100644 --- a/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts +++ b/src/vs/workbench/services/clipboard/electron-browser/clipboardService.ts @@ -8,6 +8,7 @@ import { clipboard } from 'electron'; import { URI } from 'vs/base/common/uri'; import { isMacintosh } from 'vs/base/common/platform'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; export class NativeClipboardService implements IClipboardService { @@ -15,51 +16,52 @@ export class NativeClipboardService implements IClipboardService { _serviceBrand: undefined; + constructor( + @IElectronService private readonly electronService: IElectronService + ) { } + async writeText(text: string, type?: 'selection' | 'clipboard'): Promise { - clipboard.writeText(text, type); + return this.electronService.writeClipboardText(text, type); } async readText(type?: 'selection' | 'clipboard'): Promise { - return clipboard.readText(type); + return this.electronService.readClipboardText(type); } - readTextSync(): string { - return clipboard.readText(); - } - - readFindText(): string { + async readFindText(): Promise { if (isMacintosh) { - return clipboard.readFindText(); + return this.electronService.readClipboardFindText(); } return ''; } - writeFindText(text: string): void { + async writeFindText(text: string): Promise { if (isMacintosh) { - clipboard.writeFindText(text); + return this.electronService.writeClipboardFindText(text); } } - writeResources(resources: URI[]): void { + async writeResources(resources: URI[]): Promise { if (resources.length) { - clipboard.writeBuffer(NativeClipboardService.FILE_FORMAT, this.resourcesToBuffer(resources)); + return this.electronService.writeClipboardBuffer(NativeClipboardService.FILE_FORMAT, this.resourcesToBuffer(resources)); } } - readResources(): URI[] { - return this.bufferToResources(clipboard.readBuffer(NativeClipboardService.FILE_FORMAT)); + async readResources(): Promise { + return this.bufferToResources(await this.electronService.readClipboardBuffer(NativeClipboardService.FILE_FORMAT)); } - hasResources(): boolean { - return clipboard.has(NativeClipboardService.FILE_FORMAT); + + async hasResources(): Promise { + return this.electronService.hasClipboard(NativeClipboardService.FILE_FORMAT); } private resourcesToBuffer(resources: URI[]): Buffer { return Buffer.from(resources.map(r => r.toString()).join('\n')); } - private bufferToResources(buffer: Buffer): URI[] { + private bufferToResources(buffer: Uint8Array): URI[] { if (!buffer) { return []; } @@ -75,6 +77,27 @@ export class NativeClipboardService implements IClipboardService { return []; // do not trust clipboard data } } + + /** @deprecated */ + readTextSync(): string { + return clipboard.readText(); + } + + /** @deprecated */ + readFindTextSync(): string { + if (isMacintosh) { + return clipboard.readFindText(); + } + + return ''; + } + + /** @deprecated */ + writeFindTextSync(text: string): void { + if (isMacintosh) { + clipboard.writeFindText(text); + } + } } registerSingleton(IClipboardService, NativeClipboardService, true); diff --git a/src/vs/workbench/services/contextmenu/electron-browser/contextmenuService.ts b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts similarity index 98% rename from src/vs/workbench/services/contextmenu/electron-browser/contextmenuService.ts rename to src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts index 70a68b7f35f..7fbdad95cfd 100644 --- a/src/vs/workbench/services/contextmenu/electron-browser/contextmenuService.ts +++ b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts @@ -9,7 +9,7 @@ import * as dom from 'vs/base/browser/dom'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { webFrame } from 'electron'; +import { webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { unmnemonicLabel } from 'vs/base/common/labels'; import { Event, Emitter } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -17,7 +17,7 @@ import { IContextMenuDelegate, ContextSubMenu, IContextMenuEvent } from 'vs/base import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu'; -import { popup } from 'vs/base/parts/contextmenu/electron-browser/contextmenu'; +import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu'; import { getTitleBarStyle } from 'vs/platform/windows/common/windows'; import { isMacintosh } from 'vs/base/common/platform'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; diff --git a/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts index 969a1e5a5dc..8229d42214b 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/dialogService.ts @@ -21,8 +21,8 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IProductService } from 'vs/platform/product/common/productService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { IElectronService } from 'vs/platform/electron/node/electron'; -import { MessageBoxOptions } from 'electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; +import { MessageBoxOptions } from 'vs/base/parts/sandbox/common/electronTypes'; import { fromNow } from 'vs/base/common/date'; interface IMassagedMessageBoxOptions { diff --git a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts index 6457069b1e5..071dcc85732 100644 --- a/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts +++ b/src/vs/workbench/services/dialogs/electron-browser/fileDialogService.ts @@ -3,10 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SaveDialogOptions, OpenDialogOptions } from 'electron'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; +import { SaveDialogOptions, OpenDialogOptions } from 'vs/base/parts/sandbox/common/electronTypes'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService, IDialogService, INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -16,7 +15,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { AbstractFileDialogService } from 'vs/workbench/services/dialogs/browser/abstractFileDialogService'; import { Schemas } from 'vs/base/common/network'; import { IModeService } from 'vs/editor/common/services/modeService'; diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index b025eadf1bf..8169816d162 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -63,6 +63,8 @@ export class EditorService extends Disposable implements EditorServiceImpl { //#endregion + private readonly fileEditorInputFactory = Registry.as(EditorExtensions.EditorInputFactories).getFileEditorInputFactory(); + constructor( @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, @IUntitledTextEditorService private readonly untitledTextEditorService: IUntitledTextEditorService, @@ -295,7 +297,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { } private closeOnFileDelete: boolean = false; - private fileEditorInputFactory = Registry.as(EditorExtensions.EditorInputFactories).getFileEditorInputFactory(); + private onConfigurationUpdated(configuration: IWorkbenchEditorConfiguration): void { if (typeof configuration.workbench?.editor?.closeOnFileDelete === 'boolean') { this.closeOnFileDelete = configuration.workbench.editor.closeOnFileDelete; diff --git a/src/vs/workbench/services/electron/electron-browser/electronService.ts b/src/vs/workbench/services/electron/electron-browser/electronService.ts deleted file mode 100644 index ba25ebd672d..00000000000 --- a/src/vs/workbench/services/electron/electron-browser/electronService.ts +++ /dev/null @@ -1,25 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IElectronService } from 'vs/platform/electron/node/electron'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; -import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; - -export class ElectronService { - - _serviceBrand: undefined; - - constructor( - @IMainProcessService mainProcessService: IMainProcessService, - @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService - ) { - return createChannelSender(mainProcessService.getChannel('electron'), { context: environmentService.configuration.windowId }); - } -} - -registerSingleton(IElectronService, ElectronService, true); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 165fbd000f6..350e5f9b7a4 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -15,6 +15,7 @@ import product from 'vs/platform/product/common/product'; import { memoize } from 'vs/base/common/decorators'; import { onUnexpectedError } from 'vs/base/common/errors'; import { LIGHT } from 'vs/platform/theme/common/themeService'; +import { parseLineAndColumnAware } from 'vs/base/common/extpath'; export class BrowserEnvironmentConfiguration implements IEnvironmentConfiguration { @@ -38,7 +39,20 @@ export class BrowserEnvironmentConfiguration implements IEnvironmentConfiguratio if (this.payload) { const fileToOpen = this.payload.get('openFile'); if (fileToOpen) { - return [{ fileUri: URI.parse(fileToOpen) }]; + const fileUri = URI.parse(fileToOpen); + + // Support: --goto parameter to open on line/col + if (this.payload.has('gotoLineMode')) { + const pathColumnAware = parseLineAndColumnAware(fileUri.path); + + return [{ + fileUri: fileUri.with({ path: pathColumnAware.path }), + lineNumber: pathColumnAware.line, + columnNumber: pathColumnAware.column + }]; + } + + return [{ fileUri }]; } } diff --git a/src/vs/workbench/services/extensionResourceLoader/electron-browser/extensionResourceLoaderService.ts b/src/vs/workbench/services/extensionResourceLoader/electron-sandbox/extensionResourceLoaderService.ts similarity index 100% rename from src/vs/workbench/services/extensionResourceLoader/electron-browser/extensionResourceLoaderService.ts rename to src/vs/workbench/services/extensionResourceLoader/electron-sandbox/extensionResourceLoaderService.ts diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index ee57b70741b..c7581d7c5fb 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { ChildProcess, fork } from 'child_process'; import { Server, Socket, createServer } from 'net'; -import { CrashReporterStartOptions } from 'electron'; +import { CrashReporterStartOptions } from 'vs/base/parts/sandbox/common/electronTypes'; import { getPathFromAmdModule } from 'vs/base/common/amd'; import { timeout } from 'vs/base/common/async'; import { toErrorMessage } from 'vs/base/common/errorMessage'; @@ -28,7 +28,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import product from 'vs/platform/product/common/product'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IInitData, UIKind } from 'vs/workbench/api/common/extHost.protocol'; import { MessageType, createMessageOfType, isMessageOfType } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 88f766b777b..56b1275cf9f 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ipcRenderer as ipc } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { ExtensionHostProcessWorker } from 'vs/workbench/services/extensions/electron-browser/extensionHost'; import { CachedExtensionScanner } from 'vs/workbench/services/extensions/electron-browser/cachedExtensionScanner'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -34,7 +34,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { Logger } from 'vs/workbench/services/extensions/common/extensionPoints'; import { flatten } from 'vs/base/common/arrays'; import { IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService'; import { Action } from 'vs/base/common/actions'; @@ -573,7 +573,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten public _onExtensionHostExit(code: number): void { if (this._isExtensionDevTestFromCli) { // When CLI testing make sure to exit with proper exit code - ipc.send('vscode:exit', code); + ipcRenderer.send('vscode:exit', code); } else { // Expected development extension termination: When the extension host goes down we also shutdown the window this._electronService.closeWindow(); diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index e3366db8981..54775ca1bb9 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -7,9 +7,9 @@ import { Event } from 'vs/base/common/event'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; -import { IResourceEditorInputType, IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWindowSettings, IWindowOpenable, IOpenWindowOptions, isFolderToOpen, isWorkspaceToOpen, isFileToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; +import { IWindowSettings, IWindowOpenable, IOpenWindowOptions, isFolderToOpen, isWorkspaceToOpen, isFileToOpen, IOpenEmptyWindowOptions, IPathData, IFileToOpen } from 'vs/platform/windows/common/windows'; import { pathsToEditors } from 'vs/workbench/common/editor'; import { IFileService } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; @@ -19,6 +19,7 @@ import { URI } from 'vs/base/common/uri'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { domEvent } from 'vs/base/browser/event'; import { memoize } from 'vs/base/common/decorators'; +import { parseLineAndColumnAware } from 'vs/base/common/extpath'; /** * A workspace to open in the workbench can either be: @@ -114,12 +115,11 @@ export class BrowserHostService extends Disposable implements IHostService { private async doOpenWindow(toOpen: IWindowOpenable[], options?: IOpenWindowOptions): Promise { const payload = this.preservePayload(); + const fileOpenables: IFileToOpen[] = []; - for (let i = 0; i < toOpen.length; i++) { - const openable = toOpen[i]; + for (const openable of toOpen) { openable.label = openable.label || this.getRecentLabel(openable); - // Folder if (isFolderToOpen(openable)) { this.workspaceProvider.open({ folderUri: openable.folderUri }, { reuse: this.shouldReuse(options, false /* no file */), payload }); @@ -130,23 +130,76 @@ export class BrowserHostService extends Disposable implements IHostService { this.workspaceProvider.open({ workspaceUri: openable.workspaceUri }, { reuse: this.shouldReuse(options, false /* no file */), payload }); } - // File + // File (handled later in bulk) else if (isFileToOpen(openable)) { + fileOpenables.push(openable); + } + } + + // Handle Files + if (fileOpenables.length > 0) { + + // Support diffMode + if (options?.diffMode && fileOpenables.length === 2) { + const editors = await pathsToEditors(fileOpenables, this.fileService); + if (editors.length !== 2 || !editors[0].resource || !editors[1].resource) { + return; // invalid resources + } // Same Window: open via editor service in current window if (this.shouldReuse(options, true /* file */)) { - const inputs: IResourceEditorInputType[] = await pathsToEditors([openable], this.fileService); - this.editorService.openEditors(inputs); + this.editorService.openEditor({ + leftResource: editors[0].resource, + rightResource: editors[1].resource + }); } // New Window: open into empty window else { const environment = new Map(); - environment.set('openFile', openable.fileUri.toString()); + environment.set('diffFileDetail', editors[0].resource.toString()); + environment.set('diffFileMaster', editors[1].resource.toString()); this.workspaceProvider.open(undefined, { payload: Array.from(environment.entries()) }); } } + + // Just open normally + else { + for (const openable of fileOpenables) { + + // Same Window: open via editor service in current window + if (this.shouldReuse(options, true /* file */)) { + let openables: IPathData[] = []; + + // Support: --goto parameter to open on line/col + if (options?.gotoLineMode) { + const pathColumnAware = parseLineAndColumnAware(openable.fileUri.path); + openables = [{ + fileUri: openable.fileUri.with({ path: pathColumnAware.path }), + lineNumber: pathColumnAware.line, + columnNumber: pathColumnAware.column + }]; + } else { + openables = [openable]; + } + + this.editorService.openEditors(await pathsToEditors(openables, this.fileService)); + } + + // New Window: open into empty window + else { + const environment = new Map(); + environment.set('openFile', openable.fileUri.toString()); + + if (options?.gotoLineMode) { + environment.set('gotoLineMode', 'true'); + } + + this.workspaceProvider.open(undefined, { payload: Array.from(environment.entries()) }); + } + } + } } } @@ -183,7 +236,7 @@ export class BrowserHostService extends Disposable implements IHostService { return this.labelService.getUriLabel(openable.fileUri); } - private shouldReuse(options: IOpenWindowOptions = {}, isFile: boolean): boolean { + private shouldReuse(options: IOpenWindowOptions = Object.create(null), isFile: boolean): boolean { const windowConfig = this.configurationService.getValue('window'); const openInNewWindowConfig = isFile ? (windowConfig?.openFilesInNewWindow || 'off' /* default */) : (windowConfig?.openFoldersInNewWindow || 'default' /* default */); diff --git a/src/vs/workbench/services/host/electron-browser/desktopHostService.ts b/src/vs/workbench/services/host/electron-sandbox/desktopHostService.ts similarity index 87% rename from src/vs/workbench/services/host/electron-browser/desktopHostService.ts rename to src/vs/workbench/services/host/electron-sandbox/desktopHostService.ts index 45d69aa3d91..c49a1d38043 100644 --- a/src/vs/workbench/services/host/electron-browser/desktopHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/desktopHostService.ts @@ -5,13 +5,12 @@ import { Event } from 'vs/base/common/event'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ILabelService } from 'vs/platform/label/common/label'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWindowOpenable, IOpenWindowOptions, isFolderToOpen, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { Disposable } from 'vs/base/common/lifecycle'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; export class DesktopHostService extends Disposable implements IHostService { @@ -20,15 +19,15 @@ export class DesktopHostService extends Disposable implements IHostService { constructor( @IElectronService private readonly electronService: IElectronService, @ILabelService private readonly labelService: ILabelService, - @IWorkbenchEnvironmentService private readonly environmentService: INativeWorkbenchEnvironmentService + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService ) { super(); } get onDidChangeFocus(): Event { return this._onDidChangeFocus; } private _onDidChangeFocus: Event = Event.latch(Event.any( - Event.map(Event.filter(this.electronService.onWindowFocus, id => id === this.environmentService.configuration.windowId), () => this.hasFocus), - Event.map(Event.filter(this.electronService.onWindowBlur, id => id === this.environmentService.configuration.windowId), () => this.hasFocus) + Event.map(Event.filter(this.electronService.onWindowFocus, id => id === this.electronService.windowId), () => this.hasFocus), + Event.map(Event.filter(this.electronService.onWindowBlur, id => id === this.electronService.windowId), () => this.hasFocus) )); get hasFocus(): boolean { @@ -42,7 +41,7 @@ export class DesktopHostService extends Disposable implements IHostService { return false; } - return activeWindowId === this.environmentService.configuration.windowId; + return activeWindowId === this.electronService.windowId; } openWindow(options?: IOpenEmptyWindowOptions): Promise; diff --git a/src/vs/workbench/services/issue/electron-browser/issueService.ts b/src/vs/workbench/services/issue/electron-sandbox/issueService.ts similarity index 75% rename from src/vs/workbench/services/issue/electron-browser/issueService.ts rename to src/vs/workbench/services/issue/electron-sandbox/issueService.ts index 0143cff6f3e..615f2704d51 100644 --- a/src/vs/workbench/services/issue/electron-browser/issueService.ts +++ b/src/vs/workbench/services/issue/electron-sandbox/issueService.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IIssueService } from 'vs/platform/issue/node/issue'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; -import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; +import { IIssueService } from 'vs/platform/issue/electron-sandbox/issue'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; export class IssueService { diff --git a/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts b/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts similarity index 86% rename from src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts rename to src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts index 9fe1d298205..fd388e1a2e7 100644 --- a/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts +++ b/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts @@ -3,19 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from 'vs/nls'; import { toErrorMessage } from 'vs/base/common/errorMessage'; import { ShutdownReason, StartupKind, handleVetos, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IStorageService, StorageScope, WillSaveStateReason } from 'vs/platform/storage/common/storage'; -import { ipcRenderer as ipc } from 'electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { onUnexpectedError } from 'vs/base/common/errors'; import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import Severity from 'vs/base/common/severity'; -import { localize } from 'vs/nls'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; export class NativeLifecycleService extends AbstractLifecycleService { @@ -27,7 +26,7 @@ export class NativeLifecycleService extends AbstractLifecycleService { constructor( @INotificationService private readonly notificationService: INotificationService, - @IWorkbenchEnvironmentService private readonly environmentService: INativeWorkbenchEnvironmentService, + @IElectronService private readonly electronService: IElectronService, @IStorageService readonly storageService: IStorageService, @ILogService readonly logService: ILogService ) { @@ -57,10 +56,10 @@ export class NativeLifecycleService extends AbstractLifecycleService { } private registerListeners(): void { - const windowId = this.environmentService.configuration.windowId; + const windowId = this.electronService.windowId; // Main side indicates that window is about to unload, check for vetos - ipc.on('vscode:onBeforeUnload', (_event: unknown, reply: { okChannel: string, cancelChannel: string, reason: ShutdownReason }) => { + ipcRenderer.on('vscode:onBeforeUnload', (event: unknown, reply: { okChannel: string, cancelChannel: string, reason: ShutdownReason }) => { this.logService.trace(`lifecycle: onBeforeUnload (reason: ${reply.reason})`); // trigger onBeforeShutdown events and veto collecting @@ -68,18 +67,18 @@ export class NativeLifecycleService extends AbstractLifecycleService { if (veto) { this.logService.trace('lifecycle: onBeforeUnload prevented via veto'); - ipc.send(reply.cancelChannel, windowId); + ipcRenderer.send(reply.cancelChannel, windowId); } else { this.logService.trace('lifecycle: onBeforeUnload continues without veto'); this.shutdownReason = reply.reason; - ipc.send(reply.okChannel, windowId); + ipcRenderer.send(reply.okChannel, windowId); } }); }); // Main side indicates that we will indeed shutdown - ipc.on('vscode:onWillUnload', async (_event: unknown, reply: { replyChannel: string, reason: ShutdownReason }) => { + ipcRenderer.on('vscode:onWillUnload', async (event: unknown, reply: { replyChannel: string, reason: ShutdownReason }) => { this.logService.trace(`lifecycle: onWillUnload (reason: ${reply.reason})`); // trigger onWillShutdown events and joining @@ -89,7 +88,7 @@ export class NativeLifecycleService extends AbstractLifecycleService { this._onShutdown.fire(); // acknowledge to main side - ipc.send(reply.replyChannel, windowId); + ipcRenderer.send(reply.replyChannel, windowId); }); // Save shutdown reason to retrieve on next startup diff --git a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts index 99394090da8..d8cae2cf01b 100644 --- a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts +++ b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; diff --git a/src/vs/workbench/services/log/electron-browser/logService.ts b/src/vs/workbench/services/log/electron-browser/logService.ts index 6164cb48775..caa1bd713c0 100644 --- a/src/vs/workbench/services/log/electron-browser/logService.ts +++ b/src/vs/workbench/services/log/electron-browser/logService.ts @@ -6,7 +6,7 @@ import { DelegatedLogService, ILogService, ConsoleLogInMainService, ConsoleLogService, MultiplexLogService } from 'vs/platform/log/common/log'; import { BufferLogService } from 'vs/platform/log/common/bufferLog'; import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { LoggerChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc'; import { SpdLogService } from 'vs/platform/log/node/spdlogService'; import { DisposableStore } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/services/menubar/electron-browser/menubarService.ts b/src/vs/workbench/services/menubar/electron-sandbox/menubarService.ts similarity index 75% rename from src/vs/workbench/services/menubar/electron-browser/menubarService.ts rename to src/vs/workbench/services/menubar/electron-sandbox/menubarService.ts index 9e4efbada0e..443e6b97e95 100644 --- a/src/vs/workbench/services/menubar/electron-browser/menubarService.ts +++ b/src/vs/workbench/services/menubar/electron-sandbox/menubarService.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IMenubarService } from 'vs/platform/menubar/node/menubar'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; -import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; +import { IMenubarService } from 'vs/platform/menubar/electron-sandbox/menubar'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; export class MenubarService { diff --git a/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts b/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts index c4322d81a9c..e94f6c963bd 100644 --- a/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts +++ b/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts @@ -22,6 +22,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Emitter, Event } from 'vs/base/common/event'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; class OutputChannelBackedByFile extends AbstractFileOutputChannelModel implements IOutputChannelModel { @@ -204,7 +205,8 @@ export class OutputChannelModelService extends AsbtractOutputChannelModelService constructor( @IInstantiationService instantiationService: IInstantiationService, @IWorkbenchEnvironmentService private readonly environmentService: INativeWorkbenchEnvironmentService, - @IFileService private readonly fileService: IFileService + @IFileService private readonly fileService: IFileService, + @IElectronService private readonly electronService: IElectronService ) { super(instantiationService); } @@ -217,7 +219,7 @@ export class OutputChannelModelService extends AsbtractOutputChannelModelService private _outputDir: Promise | null = null; private get outputDir(): Promise { if (!this._outputDir) { - const outputDir = URI.file(join(this.environmentService.logsPath, `output_${this.environmentService.configuration.windowId}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`)); + const outputDir = URI.file(join(this.environmentService.logsPath, `output_${this.electronService.windowId}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`)); this._outputDir = this.fileService.createFolder(outputDir).then(() => outputDir); } return this._outputDir; diff --git a/src/vs/workbench/services/request/electron-browser/requestService.ts b/src/vs/workbench/services/request/electron-sandbox/requestService.ts similarity index 93% rename from src/vs/workbench/services/request/electron-browser/requestService.ts rename to src/vs/workbench/services/request/electron-sandbox/requestService.ts index ad433fbcd2a..18ee94b099c 100644 --- a/src/vs/workbench/services/request/electron-browser/requestService.ts +++ b/src/vs/workbench/services/request/electron-sandbox/requestService.ts @@ -8,7 +8,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { RequestService } from 'vs/platform/request/browser/requestService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IRequestService } from 'vs/platform/request/common/request'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; export class NativeRequestService extends RequestService { diff --git a/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts b/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts index 8ebf99ffb30..5e60aa284ec 100644 --- a/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts +++ b/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts @@ -6,11 +6,12 @@ import { Client } from 'vs/base/parts/ipc/common/ipc.net'; import { connect } from 'vs/base/parts/ipc/node/ipc.net'; import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/common/ipc'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; export class SharedProcessService implements ISharedProcessService { @@ -21,12 +22,13 @@ export class SharedProcessService implements ISharedProcessService { constructor( @IMainProcessService mainProcessService: IMainProcessService, + @IElectronService electronService: IElectronService, @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService ) { this.sharedProcessMainChannel = mainProcessService.getChannel('sharedProcess'); this.withSharedProcessConnection = this.whenSharedProcessReady() - .then(() => connect(environmentService.sharedIPCHandle, `window:${environmentService.configuration.windowId}`)); + .then(() => connect(environmentService.sharedIPCHandle, `window:${electronService.windowId}`)); } whenSharedProcessReady(): Promise { diff --git a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts index b00bdc79286..9181a03692f 100644 --- a/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts +++ b/src/vs/workbench/services/textmodelResolver/common/textModelResolverService.ts @@ -6,7 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITextModel } from 'vs/editor/common/model'; -import { IDisposable, toDisposable, IReference, ReferenceCollection } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, IReference, ReferenceCollection, Disposable } from 'vs/base/common/lifecycle'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; import { ITextFileService, TextFileLoadReason } from 'vs/workbench/services/textfile/common/textfiles'; @@ -16,6 +16,8 @@ import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textF import { IFileService } from 'vs/platform/files/common/files'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; +import { ModelUndoRedoParticipant } from 'vs/editor/common/services/modelUndoRedoParticipant'; class ResourceModelCollection extends ReferenceCollection> { @@ -159,7 +161,7 @@ class ResourceModelCollection extends ReferenceCollection> { diff --git a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts index 9ed134bb638..3ad28da9268 100644 --- a/src/vs/workbench/services/themes/common/colorExtensionPoint.ts +++ b/src/vs/workbench/services/themes/common/colorExtensionPoint.ts @@ -32,7 +32,7 @@ const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint { this.cachedViewInfo.set(view.id, { containerId: container.id }); this.getOrCreateDefaultViewLocationContextKey(view).set(this.getDefaultContainerById(view.id) === container); }); - this.getViewContainerModel(container).add(views); + this.getViewContainerModel(container).add(views.map(view => { return { viewDescriptor: view, collapsed: expandViews ? false : undefined }; })); } private removeViews(container: ViewContainer, views: IViewDescriptor[]): void { diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 22a0bee904a..5a2ff0d3508 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef } from 'vs/workbench/common/views'; +import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef, IAddedViewDescriptorState } from 'vs/workbench/common/views'; import { IContextKeyService, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -461,12 +461,13 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode }); } - add(viewDescriptors: IViewDescriptor[]): void { + add(addedViewDescriptorStates: IAddedViewDescriptorState[]): void { const addedItems: IViewDescriptorItem[] = []; const addedActiveDescriptors: IViewDescriptor[] = []; const addedVisibleItems: { index: number, viewDescriptor: IViewDescriptor, size?: number, collapsed: boolean; }[] = []; - for (const viewDescriptor of viewDescriptors) { + for (const addedViewDescriptorState of addedViewDescriptorStates) { + const viewDescriptor = addedViewDescriptorState.viewDescriptor; if (viewDescriptor.when) { for (const key of viewDescriptor.when.keys()) { @@ -482,13 +483,13 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode } else { state.visibleGlobal = isUndefinedOrNull(state.visibleGlobal) ? !viewDescriptor.hideByDefault : state.visibleGlobal; } - state.collapsed = isUndefinedOrNull(state.collapsed) ? !!viewDescriptor.collapsed : state.collapsed; + state.collapsed = isUndefinedOrNull(addedViewDescriptorState.collapsed) ? (isUndefinedOrNull(state.collapsed) ? !!viewDescriptor.collapsed : state.collapsed) : addedViewDescriptorState.collapsed; } else { state = { active: false, visibleGlobal: !viewDescriptor.hideByDefault, visibleWorkspace: !viewDescriptor.hideByDefault, - collapsed: !!viewDescriptor.collapsed, + collapsed: isUndefinedOrNull(addedViewDescriptorState.collapsed) ? !!viewDescriptor.collapsed : addedViewDescriptorState.collapsed, }; } this.viewDescriptorsState.set(viewDescriptor.id, state); diff --git a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts index c48f999da64..c26ceb99b95 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 } from 'vs/base/common/arrays'; -import { isEqual, getComparisonKey } from 'vs/base/common/resources'; +import { isEqual, getComparisonKey, isEqualAuthority } 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'; @@ -131,7 +131,7 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi const remoteAuthority = this.environmentService.configuration.remoteAuthority; if (remoteAuthority) { // https://github.com/microsoft/vscode/issues/94191 - foldersToAdd = foldersToAdd.filter(f => f.uri.scheme !== Schemas.file && (f.uri.scheme !== Schemas.vscodeRemote || f.uri.authority === remoteAuthority)); + foldersToAdd = foldersToAdd.filter(f => f.uri.scheme !== Schemas.file && (f.uri.scheme !== Schemas.vscodeRemote || isEqualAuthority(f.uri.authority, remoteAuthority))); } // If we are in no-workspace or single-folder workspace, adding folders has to diff --git a/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts b/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts index 144b9b16f8e..ba261dea854 100644 --- a/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/electron-browser/workspaceEditingService.ts @@ -27,7 +27,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { AbstractWorkspaceEditingService } from 'vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService'; -import { IElectronService } from 'vs/platform/electron/node/electron'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { isMacintosh } from 'vs/base/common/platform'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { BackupFileService } from 'vs/workbench/services/backup/common/backupFileService'; diff --git a/src/vs/workbench/services/workspaces/electron-browser/workspacesService.ts b/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts similarity index 58% rename from src/vs/workbench/services/workspaces/electron-browser/workspacesService.ts rename to src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts index 22707759bd2..05621320243 100644 --- a/src/vs/workbench/services/workspaces/electron-browser/workspacesService.ts +++ b/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts @@ -4,11 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; -import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; +import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; +import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; export class NativeWorkspacesService { @@ -16,9 +15,9 @@ export class NativeWorkspacesService { constructor( @IMainProcessService mainProcessService: IMainProcessService, - @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService + @IElectronService electronService: IElectronService ) { - return createChannelSender(mainProcessService.getChannel('workspaces'), { context: environmentService.configuration.windowId }); + return createChannelSender(mainProcessService.getChannel('workspaces'), { context: electronService.windowId }); } } diff --git a/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts index 39820a127b2..fb797b14dd5 100644 --- a/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts @@ -762,6 +762,72 @@ suite('ExtHostLanguageFeatures', function () { assert.equal(value.edits.length, 2); }); + test('Multiple RenameProviders don\'t respect all possible PrepareRename handlers, #98352', async function () { + + let called = [false, false, false, false]; + + disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { + prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult { + called[0] = true; + let range = document.getWordRangeAtPosition(position); + return range; + } + + provideRenameEdits(): vscode.ProviderResult { + called[1] = true; + return undefined; + } + })); + + disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { + prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult { + called[2] = true; + return Promise.reject('Cannot rename this symbol2.'); + } + provideRenameEdits(): vscode.ProviderResult { + called[3] = true; + return undefined; + } + })); + + await rpcProtocol.sync(); + await rename(model, new EditorPosition(1, 1), 'newName'); + + assert.deepEqual(called, [true, true, true, false]); + }); + + test('Multiple RenameProviders don\'t respect all possible PrepareRename handlers, #98352', async function () { + + let called = [false, false, false]; + + disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { + prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult { + called[0] = true; + let range = document.getWordRangeAtPosition(position); + return range; + } + + provideRenameEdits(): vscode.ProviderResult { + called[1] = true; + return undefined; + } + })); + + disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { + + provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string,): vscode.ProviderResult { + called[2] = true; + return new types.WorkspaceEdit(); + } + })); + + await rpcProtocol.sync(); + await rename(model, new EditorPosition(1, 1), 'newName'); + + // first provider has NO prepare which means it is taken by default + assert.deepEqual(called, [false, false, true]); + }); + // --- parameter hints test('Parameter Hints, order', async () => { diff --git a/src/vs/workbench/test/browser/api/mainThreadDocuments.test.ts b/src/vs/workbench/test/browser/api/mainThreadDocuments.test.ts index a14eca8b02a..896dd76ee26 100644 --- a/src/vs/workbench/test/browser/api/mainThreadDocuments.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadDocuments.test.ts @@ -7,6 +7,7 @@ import * as assert from 'assert'; import { BoundModelReferenceCollection } from 'vs/workbench/api/browser/mainThreadDocuments'; import { createTextModel } from 'vs/editor/test/common/editorTestUtils'; import { timeout } from 'vs/base/common/async'; +import { URI } from 'vs/base/common/uri'; suite('BoundModelReferenceCollection', () => { @@ -20,12 +21,14 @@ suite('BoundModelReferenceCollection', () => { let didDispose = false; - col.add({ - object: { textEditorModel: createTextModel('farboo') }, - dispose() { - didDispose = true; - } - }); + col.add( + URI.parse('test://farboo'), + { + object: { textEditorModel: createTextModel('farboo') }, + dispose() { + didDispose = true; + } + }); await timeout(30); assert.equal(didDispose, true); @@ -35,27 +38,95 @@ suite('BoundModelReferenceCollection', () => { let disposed: number[] = []; - col.add({ - object: { textEditorModel: createTextModel('farboo') }, - dispose() { - disposed.push(0); - } - }); - col.add({ - object: { textEditorModel: createTextModel('boofar') }, - dispose() { - disposed.push(1); - } - }); + col.add( + URI.parse('test://farboo'), + { + object: { textEditorModel: createTextModel('farboo') }, + dispose() { + disposed.push(0); + } + }); - col.add({ - object: { textEditorModel: createTextModel(new Array(71).join('x')) }, - dispose() { - disposed.push(2); - } - }); + col.add( + URI.parse('test://boofar'), + { + object: { textEditorModel: createTextModel('boofar') }, + dispose() { + disposed.push(1); + } + }); + + col.add( + URI.parse('test://xxxxxxx'), + { + object: { textEditorModel: createTextModel(new Array(71).join('x')) }, + dispose() { + disposed.push(2); + } + }); assert.deepEqual(disposed, [0, 1]); }); + test('dispose uri', () => { + + let disposed: number[] = []; + + col.add( + URI.parse('test:///farboo'), + { + object: { textEditorModel: createTextModel('farboo') }, + dispose() { + disposed.push(0); + } + }); + + col.add( + URI.parse('test:///boofar'), + { + object: { textEditorModel: createTextModel('boofar') }, + dispose() { + disposed.push(1); + } + }); + + col.add( + URI.parse('test:///boo/far1'), + { + object: { textEditorModel: createTextModel('boo/far1') }, + dispose() { + disposed.push(2); + } + }); + + col.add( + URI.parse('test:///boo/far2'), + { + object: { textEditorModel: createTextModel('boo/far2') }, + dispose() { + disposed.push(3); + } + }); + + col.add( + URI.parse('test:///boo1/far'), + { + object: { textEditorModel: createTextModel('boo1/far') }, + dispose() { + disposed.push(4); + } + }); + + col.remove(URI.parse('test:///unknown')); + assert.equal(disposed.length, 0); + + col.remove(URI.parse('test:///farboo')); + assert.deepEqual(disposed, [0]); + + disposed = []; + + col.remove(URI.parse('test:///boo')); + assert.deepEqual(disposed, [2, 3]); + }); + }); diff --git a/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts b/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts index 01111a204e1..065874bd281 100644 --- a/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadDocumentsAndEditors.test.ts @@ -25,7 +25,7 @@ import { NullLogService } from 'vs/platform/log/common/log'; import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService'; import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService'; import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; -import { TestTextResourcePropertiesService } from 'vs/workbench/test/common/workbenchTestServices'; +import { TestTextResourcePropertiesService, TestWorkingCopyFileService } from 'vs/workbench/test/common/workbenchTestServices'; suite('MainThreadDocumentsAndEditors', () => { @@ -88,7 +88,8 @@ suite('MainThreadDocumentsAndEditors', () => { return undefined; } }, - TestEnvironmentService + TestEnvironmentService, + new TestWorkingCopyFileService() ); }); diff --git a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts index e4c707e454d..9cc9f8ee181 100644 --- a/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadEditors.test.ts @@ -104,6 +104,7 @@ suite('MainThreadEditors', () => { }; }); services.set(IWorkingCopyFileService, new class extends mock() { + onDidRunWorkingCopyFileOperation = Event.None; move(source: URI, target: URI) { movedResources.set(source, target); return Promise.resolve(Object.create(null)); diff --git a/src/vs/workbench/test/common/workbenchTestServices.ts b/src/vs/workbench/test/common/workbenchTestServices.ts index 3f4f21f7cec..8c9574d17be 100644 --- a/src/vs/workbench/test/common/workbenchTestServices.ts +++ b/src/vs/workbench/test/common/workbenchTestServices.ts @@ -14,8 +14,11 @@ import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderW import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; import { InMemoryStorageService, IWillSaveStateEvent } from 'vs/platform/storage/common/storage'; -import { WorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; +import { WorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { NullExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { FileOperation, IFileStatWithMetadata } from 'vs/platform/files/common/files'; export class TestTextResourcePropertiesService implements ITextResourcePropertiesService { @@ -121,6 +124,29 @@ export class TestStorageService extends InMemoryStorageService { export class TestWorkingCopyService extends WorkingCopyService { } +export class TestWorkingCopyFileService implements IWorkingCopyFileService { + + _serviceBrand: undefined; + + onWillRunWorkingCopyFileOperation: Event = Event.None; + onDidFailWorkingCopyFileOperation: Event = Event.None; + onDidRunWorkingCopyFileOperation: Event = Event.None; + + addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable { return Disposable.None; } + + async runFileOperationParticipants(target: URI, source: URI | undefined, operation: FileOperation): Promise { } + + async delete(resource: URI, options?: { useTrash?: boolean | undefined; recursive?: boolean | undefined; } | undefined): Promise { } + + registerWorkingCopyProvider(provider: (resourceOrFolder: URI) => IWorkingCopy[]): IDisposable { return Disposable.None; } + + getDirty(resource: URI): IWorkingCopy[] { return []; } + + move(source: URI, target: URI, overwrite?: boolean | undefined): Promise { throw new Error('Method not implemented.'); } + + copy(source: URI, target: URI, overwrite?: boolean | undefined): Promise { throw new Error('Method not implemented.'); } +} + export function mock(): Ctor { return function () { } as any; } diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index 0387e29d43b..f5f61e1272d 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -8,15 +8,14 @@ import { Event } from 'vs/base/common/event'; import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService'; import { NativeWorkbenchEnvironmentService, INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { NativeTextFileService, EncodingOracle, IEncodingOverride } from 'vs/workbench/services/textfile/electron-browser/nativeTextFileService'; -import { IElectronService } from 'vs/platform/electron/node/electron'; -import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { FileOperationError, IFileService } from 'vs/platform/files/common/files'; import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IDialogService, IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IDialogService, IFileDialogService, INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; import { IProductService } from 'vs/platform/product/common/productService'; import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; @@ -25,7 +24,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService import { URI } from 'vs/base/common/uri'; import { IReadTextFileOptions, ITextFileStreamContent, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel'; -import { IOpenEmptyWindowOptions, IWindowOpenable, IOpenWindowOptions } from 'vs/platform/windows/common/windows'; +import { IOpenEmptyWindowOptions, IWindowOpenable, IOpenWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows'; import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { LogLevel, ILogService } from 'vs/platform/log/common/log'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; @@ -37,7 +36,7 @@ import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { NodeTestBackupFileService } from 'vs/workbench/services/backup/test/electron-browser/backupFileService.test'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { INativeWindowConfiguration, IOpenedWindow } from 'vs/platform/windows/node/window'; +import { INativeWindowConfiguration } from 'vs/platform/windows/node/window'; import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices'; export const TestWindowConfiguration: INativeWindowConfiguration = { @@ -161,8 +160,11 @@ export class TestSharedProcessService implements ISharedProcessService { } export class TestElectronService implements IElectronService { + _serviceBrand: undefined; + readonly windowId = -1; + onWindowOpen: Event = Event.None; onWindowMaximize: Event = Event.None; onWindowUnmaximize: Event = Event.None; @@ -200,6 +202,7 @@ export class TestElectronService implements IElectronService { async setDocumentEdited(edited: boolean): Promise { } async openExternal(url: string): Promise { return false; } async updateTouchBar(): Promise { } + async moveItemToTrash(): Promise { return false; } async newWindowTab(): Promise { } async showPreviousWindowTab(): Promise { } async showNextWindowTab(): Promise { } @@ -215,6 +218,13 @@ export class TestElectronService implements IElectronService { async toggleDevTools(): Promise { } async startCrashReporter(options: Electron.CrashReporterStartOptions): Promise { } async resolveProxy(url: string): Promise { return undefined; } + async readClipboardText(type?: 'selection' | 'clipboard' | undefined): Promise { return ''; } + async writeClipboardText(text: string, type?: 'selection' | 'clipboard' | undefined): Promise { } + async readClipboardFindText(): Promise { return ''; } + async writeClipboardFindText(text: string): Promise { } + async writeClipboardBuffer(format: string, buffer: Uint8Array, type?: 'selection' | 'clipboard' | undefined): Promise { } + async readClipboardBuffer(format: string): Promise { return Uint8Array.from([]); } + async hasClipboard(format: string, type?: 'selection' | 'clipboard' | undefined): Promise { return false; } } export function workbenchInstantiationService(): ITestInstantiationService { diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index 1f90204b3e3..cb270d205c5 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -11,22 +11,29 @@ // ####################################################################### -//#region --- workbench common +//#region --- workbench common & sandbox -import 'vs/workbench/workbench.common.main'; +import 'vs/workbench/workbench.sandbox.main'; + +//#endregion + + +//#region --- workbench actions + +import 'vs/workbench/electron-browser/actions/developerActions'; //#endregion //#region --- workbench (desktop main) -import 'vs/workbench/electron-browser/desktop.contribution'; import 'vs/workbench/electron-browser/desktop.main'; //#endregion //#region --- workbench services + import 'vs/workbench/services/dialogs/electron-browser/fileDialogService'; import 'vs/workbench/services/integrity/node/integrityService'; import 'vs/workbench/services/textMate/electron-browser/textMateService'; @@ -37,7 +44,7 @@ import 'vs/workbench/services/dialogs/electron-browser/dialogService'; import 'vs/workbench/services/keybinding/electron-browser/nativeKeymapService'; import 'vs/workbench/services/keybinding/electron-browser/keybinding.contribution'; import 'vs/workbench/services/extensions/electron-browser/extensionService'; -import 'vs/workbench/services/contextmenu/electron-browser/contextmenuService'; +import 'vs/workbench/services/contextmenu/electron-sandbox/contextmenuService'; // TODO@Miguel this cannot be moved to sandbox due to https://github.com/microsoft/vscode/issues/98495 import 'vs/workbench/services/extensionManagement/electron-browser/extensionManagementServerService'; import 'vs/workbench/services/extensionManagement/electron-browser/extensionTipsService'; import 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl'; @@ -47,37 +54,23 @@ import 'vs/workbench/services/extensionManagement/node/extensionManagementServic import 'vs/workbench/services/accessibility/electron-browser/accessibilityService'; import 'vs/workbench/services/remote/node/tunnelService'; import 'vs/workbench/services/backup/node/backupFileService'; -import 'vs/workbench/services/url/electron-browser/urlService'; -import 'vs/workbench/services/workspaces/electron-browser/workspacesService'; import 'vs/workbench/services/workspaces/electron-browser/workspaceEditingService'; -import 'vs/workbench/services/userDataSync/electron-browser/storageKeysSyncRegistryService'; import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncMachinesService'; import 'vs/workbench/services/userDataSync/electron-browser/userDataSyncService'; import 'vs/workbench/services/authentication/electron-browser/authenticationTokenService'; import 'vs/workbench/services/authentication/browser/authenticationService'; -import 'vs/workbench/services/host/electron-browser/desktopHostService'; -import 'vs/workbench/services/request/electron-browser/requestService'; -import 'vs/workbench/services/lifecycle/electron-browser/lifecycleService'; import 'vs/workbench/services/sharedProcess/electron-browser/sharedProcessService'; -import 'vs/workbench/services/electron/electron-browser/electronService'; import 'vs/workbench/services/localizations/electron-browser/localizationsService'; import 'vs/workbench/services/clipboard/electron-browser/clipboardService'; -import 'vs/workbench/services/update/electron-browser/updateService'; -import 'vs/workbench/services/issue/electron-browser/issueService'; -import 'vs/workbench/services/menubar/electron-browser/menubarService'; -import 'vs/workbench/services/extensionResourceLoader/electron-browser/extensionResourceLoaderService'; import 'vs/workbench/services/path/electron-browser/pathService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService'; -import { TitlebarPart } from 'vs/workbench/electron-browser/parts/titlebar/titlebarPart'; -import { ITitleService } from 'vs/workbench/services/title/common/titleService'; import { IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync'; import { UserDataAutoSyncService } from 'vs/workbench/contrib/userDataSync/electron-browser/userDataAutoSyncService'; registerSingleton(ICredentialsService, KeytarCredentialsService, true); -registerSingleton(ITitleService, TitlebarPart); registerSingleton(IUserDataAutoSyncService, UserDataAutoSyncService); //#endregion @@ -85,9 +78,6 @@ registerSingleton(IUserDataAutoSyncService, UserDataAutoSyncService); //#region --- workbench contributions -// Localizations -import 'vs/workbench/contrib/localizations/browser/localizations.contribution'; - // Logs import 'vs/workbench/contrib/logs/electron-browser/logs.contribution'; @@ -98,16 +88,8 @@ import 'vs/workbench/contrib/tags/electron-browser/tags.contribution'; // Rapid Render Splash import 'vs/workbench/contrib/splash/electron-browser/partsSplash.contribution'; -// Explorer -import 'vs/workbench/contrib/files/electron-browser/files.contribution'; -import 'vs/workbench/contrib/files/electron-browser/fileActions.contribution'; - -// Backup -import 'vs/workbench/contrib/backup/electron-browser/backup.contribution'; - // Debug import 'vs/workbench/contrib/debug/node/debugHelperService'; -import 'vs/workbench/contrib/debug/electron-browser/extensionHostDebugService'; // Webview import 'vs/workbench/contrib/webview/electron-browser/webview.contribution'; @@ -148,9 +130,6 @@ import 'vs/workbench/contrib/tasks/electron-browser/taskService'; // User Data Sync import 'vs/workbench/contrib/userDataSync/electron-browser/userDataSync.contribution'; -// Telemetry Opt Out -import 'vs/workbench/contrib/welcome/telemetryOptOut/electron-browser/telemetryOptOut.contribution'; - // Configuration Exporter import 'vs/workbench/contrib/configExporter/electron-browser/configurationExportHelper.contribution'; diff --git a/src/vs/workbench/workbench.sandbox.main.ts b/src/vs/workbench/workbench.sandbox.main.ts new file mode 100644 index 00000000000..dd514a58ff6 --- /dev/null +++ b/src/vs/workbench/workbench.sandbox.main.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +// ####################################################################### +// ### ### +// ### !!! PLEASE ADD COMMON IMPORTS INTO WORKBENCH.COMMON.MAIN.TS !!! ### +// ### ### +// ####################################################################### + +//#region --- workbench common + +import 'vs/workbench/workbench.common.main'; + +//#endregion + + +//#region --- workbench services + +import 'vs/workbench/services/workspaces/electron-sandbox/workspacesService'; +import 'vs/workbench/services/userDataSync/electron-sandbox/storageKeysSyncRegistryService'; +import 'vs/workbench/services/menubar/electron-sandbox/menubarService'; +import 'vs/workbench/services/issue/electron-sandbox/issueService'; +import 'vs/workbench/services/update/electron-sandbox/updateService'; +import 'vs/workbench/services/url/electron-sandbox/urlService'; +import 'vs/workbench/services/lifecycle/electron-sandbox/lifecycleService'; +import 'vs/workbench/services/title/electron-sandbox/titleService'; +import 'vs/workbench/services/host/electron-sandbox/desktopHostService'; +import 'vs/workbench/services/request/electron-sandbox/requestService'; +import 'vs/workbench/services/extensionResourceLoader/electron-sandbox/extensionResourceLoaderService'; + +//#endregion + + +//#region --- workbench contributions + +// Localizations +import 'vs/workbench/contrib/localizations/browser/localizations.contribution'; + +// Desktop +import 'vs/workbench/electron-sandbox/desktop.contribution'; + +// Explorer +import 'vs/workbench/contrib/files/electron-sandbox/files.contribution'; +import 'vs/workbench/contrib/files/electron-sandbox/fileActions.contribution'; + +// Backup +import 'vs/workbench/contrib/backup/electron-sandbox/backup.contribution'; + +// CodeEditor Contributions +import 'vs/workbench/contrib/codeEditor/electron-sandbox/codeEditor.contribution'; + +// Debug +import 'vs/workbench/contrib/debug/electron-sandbox/extensionHostDebugService'; + +// Telemetry Opt Out +import 'vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.contribution'; + +//#endregion diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 9d89286a67e..29951124873 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -26,6 +26,7 @@ import 'vs/workbench/browser/web.main'; //#region --- workbench services + import 'vs/workbench/services/integrity/browser/integrityService'; import 'vs/workbench/services/textMate/browser/textMateService'; import 'vs/workbench/services/search/common/searchService'; diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index 51c085de716..4f1565f1a96 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -316,7 +316,7 @@ describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => { if (!opts.web) { setupDataLossTests(); } if (!opts.web) { setupDataPreferencesTests(); } setupDataSearchTests(); - setupDataNotebookTests(); + if (!opts.web) { setupDataNotebookTests(); } setupDataLanguagesTests(); setupDataEditorTests(); setupDataStatusbarTests(!!opts.web); diff --git a/test/unit/browser/index.js b/test/unit/browser/index.js index 71514111a10..926d96f6352 100644 --- a/test/unit/browser/index.js +++ b/test/unit/browser/index.js @@ -72,7 +72,7 @@ function ensureIsArray(a) { const testModules = (async function () { - const excludeGlob = '**/{node,electron-browser,electron-main}/**/*.test.js'; + const excludeGlob = '**/{node,electron-sandbox,electron-browser,electron-main}/**/*.test.js'; let isDefaultModules = true; let promise; diff --git a/test/unit/electron/index.js b/test/unit/electron/index.js index b72b59a91e9..93a49579361 100644 --- a/test/unit/electron/index.js +++ b/test/unit/electron/index.js @@ -116,7 +116,7 @@ app.on('ready', () => { nodeIntegration: true, webSecurity: false, webviewTag: true, - enableWebSQL: false + preload: path.join(__dirname, '..', '..', '..', 'src', 'vs', 'base', 'parts', 'sandbox', 'electron-browser', 'preload.js') // ensure similar environment as VSCode as tests may depend on this } }); diff --git a/yarn.lock b/yarn.lock index 767b2e1edeb..e559825232d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2715,10 +2715,10 @@ electron-to-chromium@^1.2.7: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d" integrity sha1-eOy4o5kGYYe7N07t412ccFZagD0= -electron@8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/electron/-/electron-8.3.0.tgz#c2b565a4c10d6d287d20164bcd5a478468b940a9" - integrity sha512-XRjiIJICZCgUr2vKSUI2PTkfP0gPFqCtqJUaTJSfCTuE3nTrxBKOUNeRMuCzEqspKkpFQU3SB3MdbMSHmZARlQ== +electron@7.2.4: + version "7.2.4" + resolved "https://registry.yarnpkg.com/electron/-/electron-7.2.4.tgz#9fc0446dae23ead897af8742470cb18da55c6ce9" + integrity sha512-Z+R692uTzXgP8AHrabE+kkrMlQJ6pnAYoINenwj9QSqaD2YbO8IuXU9DMCcUY0+VpA91ee09wFZJNUKYPMnCKg== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12"