From 94f12a0269b72dbcf9c1fa8f59c402c98ca24267 Mon Sep 17 00:00:00 2001 From: jeanp413 Date: Fri, 7 Aug 2020 22:26:29 -0500 Subject: [PATCH 01/98] Fixes #104144 --- src/vs/base/browser/ui/list/listView.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 5cecaeb44e4..c681515bca8 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -892,7 +892,9 @@ export class ListView implements ISpliceable, IDisposable { this.render(previousRenderRange, e.scrollTop, e.height, e.scrollLeft, e.scrollWidth); if (this.supportDynamicHeights) { - this._rerender(e.scrollTop, e.height); + // Don't update scrollTop from within an scroll event + // so we don't break smooth scrolling. #104144 + this._rerender(e.scrollTop, e.height, false); } } catch (err) { console.error('Got bad scroll event:', e); @@ -1162,7 +1164,7 @@ export class ListView implements ISpliceable, IDisposable { * Given a stable rendered state, checks every rendered element whether it needs * to be probed for dynamic height. Adjusts scroll height and top if necessary. */ - private _rerender(renderTop: number, renderHeight: number): void { + private _rerender(renderTop: number, renderHeight: number, updateScrollTop: boolean = true): void { const previousRenderRange = this.getRenderRange(renderTop, renderHeight); // Let's remember the second element's position, this helps in scrolling up @@ -1228,7 +1230,7 @@ export class ListView implements ISpliceable, IDisposable { } } - if (typeof anchorElementIndex === 'number') { + if (updateScrollTop && typeof anchorElementIndex === 'number') { this.scrollTop = this.elementTop(anchorElementIndex) - anchorElementTopDelta!; } From 425da6772868aa09b4ea42095831adedfe65789d Mon Sep 17 00:00:00 2001 From: Caio Date: Sun, 9 Aug 2020 19:05:57 -0300 Subject: [PATCH 02/98] treat .c++ & .h++ files as c++, & update icon theme --- build/win32/code.iss | 14 + extensions/cpp/package.json | 3 +- .../theme-seti/build/update-icon-theme.js | 2 +- extensions/theme-seti/cgmanifest.json | 2 +- extensions/theme-seti/icons/seti.woff | Bin 34972 -> 35272 bytes .../theme-seti/icons/vs-seti-icon-theme.json | 620 ++++++++++-------- 6 files changed, 348 insertions(+), 293 deletions(-) diff --git a/build/win32/code.iss b/build/win32/code.iss index 195e63cf12a..3192b62f1e2 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -173,6 +173,13 @@ Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.bower Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.bowerrc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\bower.ico"; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.bowerrc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.c++\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.c++\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.c++"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.c++"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,C++}"; Flags: uninsdeletekey; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.c++"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#AppUserId}"; Flags: uninsdeletekey; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.c++\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\cpp.ico"; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.c++\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles + Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.c\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.c\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.c"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.c"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,C}"; Flags: uninsdeletekey; Tasks: associatewithfiles @@ -442,6 +449,13 @@ Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.hbs"; Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.hbs\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\default.ico"; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.hbs\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.h++\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.h++\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.h++"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.h++"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,C++ Header}"; Flags: uninsdeletekey; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.h++"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#AppUserId}"; Flags: uninsdeletekey; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.h++\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\cpp.ico"; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.h++\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles + Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.hh\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.hh\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.hh"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.hh"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,C++ Header}"; Flags: uninsdeletekey; Tasks: associatewithfiles diff --git a/extensions/cpp/package.json b/extensions/cpp/package.json index e02009fb57f..1c8a244d285 100644 --- a/extensions/cpp/package.json +++ b/extensions/cpp/package.json @@ -34,7 +34,8 @@ ".c++", ".hpp", ".hh", - ".hxx", + ".hxx", + ".h++", ".h", ".ii", ".ino", diff --git a/extensions/theme-seti/build/update-icon-theme.js b/extensions/theme-seti/build/update-icon-theme.js index 77165bc5376..85228d704bf 100644 --- a/extensions/theme-seti/build/update-icon-theme.js +++ b/extensions/theme-seti/build/update-icon-theme.js @@ -305,7 +305,7 @@ exports.update = function () { } return download(fileAssociationFile).then(function (content) { - let regex2 = /\.icon-(?:set|partial)\(['"]([\w-\.]+)['"],\s*['"]([\w-]+)['"],\s*(@[\w-]+)\)/g; + let regex2 = /\.icon-(?:set|partial)\(['"]([\w-\.+]+)['"],\s*['"]([\w-]+)['"],\s*(@[\w-]+)\)/g; while ((match = regex2.exec(content)) !== null) { let pattern = match[1]; let def = '_' + match[2]; diff --git a/extensions/theme-seti/cgmanifest.json b/extensions/theme-seti/cgmanifest.json index b3bb41d3eb9..8899dae032b 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": "f3b2775662b0075aab56e5f0c03269f21f3f0f30" + "commitHash": "719e5d384e878b0e190abc80247a8726f083a393" } }, "version": "0.1.0" diff --git a/extensions/theme-seti/icons/seti.woff b/extensions/theme-seti/icons/seti.woff index 5dc3bb8d9b0386a5cd2b60a122305f7040296dac..a7c47a3ce0c5aa65cdf6c6f79e8b49c630216529 100644 GIT binary patch delta 35003 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 DfDDbM diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index a1f5817da5c..4fec9d23605 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -254,1119 +254,1141 @@ "fontCharacter": "\\E01C", "fontColor": "#8dc149" }, - "_d_light": { + "_cu_light": { "fontCharacter": "\\E01D", + "fontColor": "#7fae42" + }, + "_cu": { + "fontCharacter": "\\E01D", + "fontColor": "#8dc149" + }, + "_cu_1_light": { + "fontCharacter": "\\E01D", + "fontColor": "#9068b0" + }, + "_cu_1": { + "fontCharacter": "\\E01D", + "fontColor": "#a074c4" + }, + "_d_light": { + "fontCharacter": "\\E01E", "fontColor": "#b8383d" }, "_d": { - "fontCharacter": "\\E01D", + "fontCharacter": "\\E01E", "fontColor": "#cc3e44" }, "_dart_light": { - "fontCharacter": "\\E01E", + "fontCharacter": "\\E01F", "fontColor": "#498ba7" }, "_dart": { - "fontCharacter": "\\E01E", + "fontCharacter": "\\E01F", "fontColor": "#519aba" }, "_db_light": { - "fontCharacter": "\\E01F", + "fontCharacter": "\\E020", "fontColor": "#dd4b78" }, "_db": { - "fontCharacter": "\\E01F", + "fontCharacter": "\\E020", "fontColor": "#f55385" }, "_default_light": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#bfc2c1" }, "_default": { - "fontCharacter": "\\E020", + "fontCharacter": "\\E021", "fontColor": "#d4d7d6" }, "_docker_light": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#498ba7" }, "_docker": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#519aba" }, "_docker_1_light": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#455155" }, "_docker_1": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#4d5a5e" }, "_docker_2_light": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#7fae42" }, "_docker_2": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#8dc149" }, "_docker_3_light": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#dd4b78" }, "_docker_3": { - "fontCharacter": "\\E022", + "fontCharacter": "\\E023", "fontColor": "#f55385" }, "_ejs_light": { - "fontCharacter": "\\E024", + "fontCharacter": "\\E025", "fontColor": "#b7b73b" }, "_ejs": { - "fontCharacter": "\\E024", + "fontCharacter": "\\E025", "fontColor": "#cbcb41" }, "_elixir_light": { - "fontCharacter": "\\E025", + "fontCharacter": "\\E026", "fontColor": "#9068b0" }, "_elixir": { - "fontCharacter": "\\E025", + "fontCharacter": "\\E026", "fontColor": "#a074c4" }, "_elixir_script_light": { - "fontCharacter": "\\E026", + "fontCharacter": "\\E027", "fontColor": "#9068b0" }, "_elixir_script": { - "fontCharacter": "\\E026", + "fontCharacter": "\\E027", "fontColor": "#a074c4" }, "_elm_light": { - "fontCharacter": "\\E027", + "fontCharacter": "\\E028", "fontColor": "#498ba7" }, "_elm": { - "fontCharacter": "\\E027", + "fontCharacter": "\\E028", "fontColor": "#519aba" }, "_eslint_light": { - "fontCharacter": "\\E029", + "fontCharacter": "\\E02A", "fontColor": "#9068b0" }, "_eslint": { - "fontCharacter": "\\E029", + "fontCharacter": "\\E02A", "fontColor": "#a074c4" }, "_eslint_1_light": { - "fontCharacter": "\\E029", + "fontCharacter": "\\E02A", "fontColor": "#455155" }, "_eslint_1": { - "fontCharacter": "\\E029", + "fontCharacter": "\\E02A", "fontColor": "#4d5a5e" }, "_ethereum_light": { - "fontCharacter": "\\E02A", + "fontCharacter": "\\E02B", "fontColor": "#498ba7" }, "_ethereum": { - "fontCharacter": "\\E02A", + "fontCharacter": "\\E02B", "fontColor": "#519aba" }, "_f-sharp_light": { - "fontCharacter": "\\E02B", + "fontCharacter": "\\E02C", "fontColor": "#498ba7" }, "_f-sharp": { - "fontCharacter": "\\E02B", + "fontCharacter": "\\E02C", "fontColor": "#519aba" }, "_favicon_light": { - "fontCharacter": "\\E02C", + "fontCharacter": "\\E02D", "fontColor": "#b7b73b" }, "_favicon": { - "fontCharacter": "\\E02C", + "fontCharacter": "\\E02D", "fontColor": "#cbcb41" }, "_firebase_light": { - "fontCharacter": "\\E02D", + "fontCharacter": "\\E02E", "fontColor": "#cc6d2e" }, "_firebase": { - "fontCharacter": "\\E02D", + "fontCharacter": "\\E02E", "fontColor": "#e37933" }, "_firefox_light": { - "fontCharacter": "\\E02E", + "fontCharacter": "\\E02F", "fontColor": "#cc6d2e" }, "_firefox": { - "fontCharacter": "\\E02E", + "fontCharacter": "\\E02F", "fontColor": "#e37933" }, "_font_light": { - "fontCharacter": "\\E030", + "fontCharacter": "\\E031", "fontColor": "#b8383d" }, "_font": { - "fontCharacter": "\\E030", + "fontCharacter": "\\E031", "fontColor": "#cc3e44" }, "_git_light": { - "fontCharacter": "\\E031", + "fontCharacter": "\\E032", "fontColor": "#3b4b52" }, "_git": { - "fontCharacter": "\\E031", + "fontCharacter": "\\E032", "fontColor": "#41535b" }, "_go_light": { - "fontCharacter": "\\E035", + "fontCharacter": "\\E036", "fontColor": "#498ba7" }, "_go": { - "fontCharacter": "\\E035", + "fontCharacter": "\\E036", "fontColor": "#519aba" }, "_go2_light": { - "fontCharacter": "\\E036", + "fontCharacter": "\\E037", "fontColor": "#498ba7" }, "_go2": { - "fontCharacter": "\\E036", + "fontCharacter": "\\E037", "fontColor": "#519aba" }, "_gradle_light": { - "fontCharacter": "\\E037", - "fontColor": "#7fae42" + "fontCharacter": "\\E038", + "fontColor": "#498ba7" }, "_gradle": { - "fontCharacter": "\\E037", - "fontColor": "#8dc149" + "fontCharacter": "\\E038", + "fontColor": "#519aba" }, "_grails_light": { - "fontCharacter": "\\E038", + "fontCharacter": "\\E039", "fontColor": "#7fae42" }, "_grails": { - "fontCharacter": "\\E038", + "fontCharacter": "\\E039", "fontColor": "#8dc149" }, "_graphql_light": { - "fontCharacter": "\\E039", + "fontCharacter": "\\E03A", "fontColor": "#dd4b78" }, "_graphql": { - "fontCharacter": "\\E039", + "fontCharacter": "\\E03A", "fontColor": "#f55385" }, "_grunt_light": { - "fontCharacter": "\\E03A", + "fontCharacter": "\\E03B", "fontColor": "#cc6d2e" }, "_grunt": { - "fontCharacter": "\\E03A", + "fontCharacter": "\\E03B", "fontColor": "#e37933" }, "_gulp_light": { - "fontCharacter": "\\E03B", + "fontCharacter": "\\E03C", "fontColor": "#b8383d" }, "_gulp": { - "fontCharacter": "\\E03B", + "fontCharacter": "\\E03C", "fontColor": "#cc3e44" }, "_haml_light": { - "fontCharacter": "\\E03D", + "fontCharacter": "\\E03E", "fontColor": "#b8383d" }, "_haml": { - "fontCharacter": "\\E03D", + "fontCharacter": "\\E03E", "fontColor": "#cc3e44" }, "_happenings_light": { - "fontCharacter": "\\E03E", + "fontCharacter": "\\E03F", "fontColor": "#498ba7" }, "_happenings": { - "fontCharacter": "\\E03E", + "fontCharacter": "\\E03F", "fontColor": "#519aba" }, "_haskell_light": { - "fontCharacter": "\\E03F", + "fontCharacter": "\\E040", "fontColor": "#9068b0" }, "_haskell": { - "fontCharacter": "\\E03F", + "fontCharacter": "\\E040", "fontColor": "#a074c4" }, "_haxe_light": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#cc6d2e" }, "_haxe": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#e37933" }, "_haxe_1_light": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#b7b73b" }, "_haxe_1": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#cbcb41" }, "_haxe_2_light": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#498ba7" }, "_haxe_2": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#519aba" }, "_haxe_3_light": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#9068b0" }, "_haxe_3": { - "fontCharacter": "\\E040", + "fontCharacter": "\\E041", "fontColor": "#a074c4" }, "_heroku_light": { - "fontCharacter": "\\E041", + "fontCharacter": "\\E042", "fontColor": "#9068b0" }, "_heroku": { - "fontCharacter": "\\E041", + "fontCharacter": "\\E042", "fontColor": "#a074c4" }, "_hex_light": { - "fontCharacter": "\\E042", + "fontCharacter": "\\E043", "fontColor": "#b8383d" }, "_hex": { - "fontCharacter": "\\E042", + "fontCharacter": "\\E043", "fontColor": "#cc3e44" }, "_html_light": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#498ba7" }, "_html": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#519aba" }, "_html_1_light": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#7fae42" }, "_html_1": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#8dc149" }, "_html_2_light": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#b7b73b" }, "_html_2": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#cbcb41" }, "_html_3_light": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#cc6d2e" }, "_html_3": { - "fontCharacter": "\\E043", + "fontCharacter": "\\E044", "fontColor": "#e37933" }, "_html_erb_light": { - "fontCharacter": "\\E044", + "fontCharacter": "\\E045", "fontColor": "#b8383d" }, "_html_erb": { - "fontCharacter": "\\E044", + "fontCharacter": "\\E045", "fontColor": "#cc3e44" }, "_ignored_light": { - "fontCharacter": "\\E045", + "fontCharacter": "\\E046", "fontColor": "#3b4b52" }, "_ignored": { - "fontCharacter": "\\E045", + "fontCharacter": "\\E046", "fontColor": "#41535b" }, "_illustrator_light": { - "fontCharacter": "\\E046", + "fontCharacter": "\\E047", "fontColor": "#b7b73b" }, "_illustrator": { - "fontCharacter": "\\E046", + "fontCharacter": "\\E047", "fontColor": "#cbcb41" }, "_image_light": { - "fontCharacter": "\\E047", + "fontCharacter": "\\E048", "fontColor": "#9068b0" }, "_image": { - "fontCharacter": "\\E047", + "fontCharacter": "\\E048", "fontColor": "#a074c4" }, "_info_light": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E049", "fontColor": "#498ba7" }, "_info": { - "fontCharacter": "\\E048", + "fontCharacter": "\\E049", "fontColor": "#519aba" }, "_ionic_light": { - "fontCharacter": "\\E049", + "fontCharacter": "\\E04A", "fontColor": "#498ba7" }, "_ionic": { - "fontCharacter": "\\E049", + "fontCharacter": "\\E04A", "fontColor": "#519aba" }, "_jade_light": { - "fontCharacter": "\\E04A", + "fontCharacter": "\\E04B", "fontColor": "#b8383d" }, "_jade": { - "fontCharacter": "\\E04A", + "fontCharacter": "\\E04B", "fontColor": "#cc3e44" }, "_java_light": { - "fontCharacter": "\\E04B", + "fontCharacter": "\\E04C", "fontColor": "#b8383d" }, "_java": { - "fontCharacter": "\\E04B", + "fontCharacter": "\\E04C", "fontColor": "#cc3e44" }, "_javascript_light": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04D", "fontColor": "#b7b73b" }, "_javascript": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04D", "fontColor": "#cbcb41" }, "_javascript_1_light": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04D", "fontColor": "#cc6d2e" }, "_javascript_1": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04D", "fontColor": "#e37933" }, "_javascript_2_light": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04D", "fontColor": "#498ba7" }, "_javascript_2": { - "fontCharacter": "\\E04C", + "fontCharacter": "\\E04D", "fontColor": "#519aba" }, "_jenkins_light": { - "fontCharacter": "\\E04D", + "fontCharacter": "\\E04E", "fontColor": "#b8383d" }, "_jenkins": { - "fontCharacter": "\\E04D", + "fontCharacter": "\\E04E", "fontColor": "#cc3e44" }, "_jinja_light": { - "fontCharacter": "\\E04E", + "fontCharacter": "\\E04F", "fontColor": "#b8383d" }, "_jinja": { - "fontCharacter": "\\E04E", + "fontCharacter": "\\E04F", "fontColor": "#cc3e44" }, "_json_light": { - "fontCharacter": "\\E050", + "fontCharacter": "\\E051", "fontColor": "#b7b73b" }, "_json": { - "fontCharacter": "\\E050", + "fontCharacter": "\\E051", "fontColor": "#cbcb41" }, "_json_1_light": { - "fontCharacter": "\\E050", + "fontCharacter": "\\E051", "fontColor": "#7fae42" }, "_json_1": { - "fontCharacter": "\\E050", + "fontCharacter": "\\E051", "fontColor": "#8dc149" }, "_julia_light": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E052", "fontColor": "#9068b0" }, "_julia": { - "fontCharacter": "\\E051", + "fontCharacter": "\\E052", "fontColor": "#a074c4" }, "_karma_light": { - "fontCharacter": "\\E052", + "fontCharacter": "\\E053", "fontColor": "#7fae42" }, "_karma": { - "fontCharacter": "\\E052", + "fontCharacter": "\\E053", "fontColor": "#8dc149" }, "_kotlin_light": { - "fontCharacter": "\\E053", + "fontCharacter": "\\E054", "fontColor": "#cc6d2e" }, "_kotlin": { - "fontCharacter": "\\E053", + "fontCharacter": "\\E054", "fontColor": "#e37933" }, "_less_light": { - "fontCharacter": "\\E054", + "fontCharacter": "\\E055", "fontColor": "#498ba7" }, "_less": { - "fontCharacter": "\\E054", + "fontCharacter": "\\E055", "fontColor": "#519aba" }, "_license_light": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E056", "fontColor": "#b7b73b" }, "_license": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E056", "fontColor": "#cbcb41" }, "_license_1_light": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E056", "fontColor": "#cc6d2e" }, "_license_1": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E056", "fontColor": "#e37933" }, "_license_2_light": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E056", "fontColor": "#b8383d" }, "_license_2": { - "fontCharacter": "\\E055", + "fontCharacter": "\\E056", "fontColor": "#cc3e44" }, "_liquid_light": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E057", "fontColor": "#7fae42" }, "_liquid": { - "fontCharacter": "\\E056", + "fontCharacter": "\\E057", "fontColor": "#8dc149" }, "_livescript_light": { - "fontCharacter": "\\E057", + "fontCharacter": "\\E058", "fontColor": "#498ba7" }, "_livescript": { - "fontCharacter": "\\E057", + "fontCharacter": "\\E058", "fontColor": "#519aba" }, "_lock_light": { - "fontCharacter": "\\E058", + "fontCharacter": "\\E059", "fontColor": "#7fae42" }, "_lock": { - "fontCharacter": "\\E058", + "fontCharacter": "\\E059", "fontColor": "#8dc149" }, "_lua_light": { - "fontCharacter": "\\E059", + "fontCharacter": "\\E05A", "fontColor": "#498ba7" }, "_lua": { - "fontCharacter": "\\E059", + "fontCharacter": "\\E05A", "fontColor": "#519aba" }, "_makefile_light": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#cc6d2e" }, "_makefile": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#e37933" }, "_makefile_1_light": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#9068b0" }, "_makefile_1": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#a074c4" }, "_makefile_2_light": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#627379" }, "_makefile_2": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#6d8086" }, "_makefile_3_light": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#498ba7" }, "_makefile_3": { - "fontCharacter": "\\E05A", + "fontCharacter": "\\E05B", "fontColor": "#519aba" }, "_markdown_light": { - "fontCharacter": "\\E05B", + "fontCharacter": "\\E05C", "fontColor": "#498ba7" }, "_markdown": { - "fontCharacter": "\\E05B", + "fontCharacter": "\\E05C", "fontColor": "#519aba" }, "_maven_light": { - "fontCharacter": "\\E05C", + "fontCharacter": "\\E05D", "fontColor": "#b8383d" }, "_maven": { - "fontCharacter": "\\E05C", + "fontCharacter": "\\E05D", "fontColor": "#cc3e44" }, "_mdo_light": { - "fontCharacter": "\\E05D", + "fontCharacter": "\\E05E", "fontColor": "#b8383d" }, "_mdo": { - "fontCharacter": "\\E05D", + "fontCharacter": "\\E05E", "fontColor": "#cc3e44" }, "_mustache_light": { - "fontCharacter": "\\E05E", + "fontCharacter": "\\E05F", "fontColor": "#cc6d2e" }, "_mustache": { - "fontCharacter": "\\E05E", + "fontCharacter": "\\E05F", "fontColor": "#e37933" }, + "_nim_light": { + "fontColor": "#b7b73b" + }, + "_nim": { + "fontColor": "#cbcb41" + }, "_npm_light": { - "fontCharacter": "\\E060", + "fontCharacter": "\\E061", "fontColor": "#3b4b52" }, "_npm": { - "fontCharacter": "\\E060", + "fontCharacter": "\\E061", "fontColor": "#41535b" }, "_npm_1_light": { - "fontCharacter": "\\E060", + "fontCharacter": "\\E061", "fontColor": "#b8383d" }, "_npm_1": { - "fontCharacter": "\\E060", + "fontCharacter": "\\E061", "fontColor": "#cc3e44" }, "_npm_ignored_light": { - "fontCharacter": "\\E061", + "fontCharacter": "\\E062", "fontColor": "#3b4b52" }, "_npm_ignored": { - "fontCharacter": "\\E061", + "fontCharacter": "\\E062", "fontColor": "#41535b" }, "_nunjucks_light": { - "fontCharacter": "\\E062", + "fontCharacter": "\\E063", "fontColor": "#7fae42" }, "_nunjucks": { - "fontCharacter": "\\E062", + "fontCharacter": "\\E063", "fontColor": "#8dc149" }, "_ocaml_light": { - "fontCharacter": "\\E063", + "fontCharacter": "\\E064", "fontColor": "#cc6d2e" }, "_ocaml": { - "fontCharacter": "\\E063", + "fontCharacter": "\\E064", "fontColor": "#e37933" }, "_odata_light": { - "fontCharacter": "\\E064", + "fontCharacter": "\\E065", "fontColor": "#cc6d2e" }, "_odata": { - "fontCharacter": "\\E064", + "fontCharacter": "\\E065", "fontColor": "#e37933" }, "_pddl_light": { - "fontCharacter": "\\E065", + "fontCharacter": "\\E066", "fontColor": "#9068b0" }, "_pddl": { - "fontCharacter": "\\E065", + "fontCharacter": "\\E066", "fontColor": "#a074c4" }, "_pdf_light": { - "fontCharacter": "\\E066", + "fontCharacter": "\\E067", "fontColor": "#b8383d" }, "_pdf": { - "fontCharacter": "\\E066", + "fontCharacter": "\\E067", "fontColor": "#cc3e44" }, "_perl_light": { - "fontCharacter": "\\E067", + "fontCharacter": "\\E068", "fontColor": "#498ba7" }, "_perl": { - "fontCharacter": "\\E067", + "fontCharacter": "\\E068", "fontColor": "#519aba" }, "_photoshop_light": { - "fontCharacter": "\\E068", + "fontCharacter": "\\E069", "fontColor": "#498ba7" }, "_photoshop": { - "fontCharacter": "\\E068", + "fontCharacter": "\\E069", "fontColor": "#519aba" }, "_php_light": { - "fontCharacter": "\\E069", + "fontCharacter": "\\E06A", "fontColor": "#9068b0" }, "_php": { - "fontCharacter": "\\E069", + "fontCharacter": "\\E06A", "fontColor": "#a074c4" }, "_plan_light": { - "fontCharacter": "\\E06A", + "fontCharacter": "\\E06B", "fontColor": "#7fae42" }, "_plan": { - "fontCharacter": "\\E06A", + "fontCharacter": "\\E06B", "fontColor": "#8dc149" }, "_platformio_light": { - "fontCharacter": "\\E06B", + "fontCharacter": "\\E06C", "fontColor": "#cc6d2e" }, "_platformio": { - "fontCharacter": "\\E06B", + "fontCharacter": "\\E06C", "fontColor": "#e37933" }, "_powershell_light": { - "fontCharacter": "\\E06C", + "fontCharacter": "\\E06D", "fontColor": "#498ba7" }, "_powershell": { - "fontCharacter": "\\E06C", + "fontCharacter": "\\E06D", "fontColor": "#519aba" }, "_prolog_light": { - "fontCharacter": "\\E06E", + "fontCharacter": "\\E06F", "fontColor": "#cc6d2e" }, "_prolog": { - "fontCharacter": "\\E06E", + "fontCharacter": "\\E06F", "fontColor": "#e37933" }, "_pug_light": { - "fontCharacter": "\\E06F", + "fontCharacter": "\\E070", "fontColor": "#b8383d" }, "_pug": { - "fontCharacter": "\\E06F", + "fontCharacter": "\\E070", "fontColor": "#cc3e44" }, "_puppet_light": { - "fontCharacter": "\\E070", + "fontCharacter": "\\E071", "fontColor": "#b7b73b" }, "_puppet": { - "fontCharacter": "\\E070", + "fontCharacter": "\\E071", "fontColor": "#cbcb41" }, "_python_light": { - "fontCharacter": "\\E071", + "fontCharacter": "\\E072", "fontColor": "#498ba7" }, "_python": { - "fontCharacter": "\\E071", + "fontCharacter": "\\E072", "fontColor": "#519aba" }, "_react_light": { - "fontCharacter": "\\E073", + "fontCharacter": "\\E074", "fontColor": "#498ba7" }, "_react": { - "fontCharacter": "\\E073", + "fontCharacter": "\\E074", "fontColor": "#519aba" }, "_react_1_light": { - "fontCharacter": "\\E073", + "fontCharacter": "\\E074", "fontColor": "#cc6d2e" }, "_react_1": { - "fontCharacter": "\\E073", + "fontCharacter": "\\E074", "fontColor": "#e37933" }, "_react_2_light": { - "fontCharacter": "\\E073", + "fontCharacter": "\\E074", "fontColor": "#b7b73b" }, "_react_2": { - "fontCharacter": "\\E073", + "fontCharacter": "\\E074", "fontColor": "#cbcb41" }, "_reasonml_light": { - "fontCharacter": "\\E074", + "fontCharacter": "\\E075", "fontColor": "#b8383d" }, "_reasonml": { - "fontCharacter": "\\E074", + "fontCharacter": "\\E075", "fontColor": "#cc3e44" }, "_rollup_light": { - "fontCharacter": "\\E075", + "fontCharacter": "\\E076", "fontColor": "#b8383d" }, "_rollup": { - "fontCharacter": "\\E075", + "fontCharacter": "\\E076", "fontColor": "#cc3e44" }, "_ruby_light": { - "fontCharacter": "\\E076", + "fontCharacter": "\\E077", "fontColor": "#b8383d" }, "_ruby": { - "fontCharacter": "\\E076", + "fontCharacter": "\\E077", "fontColor": "#cc3e44" }, "_rust_light": { - "fontCharacter": "\\E077", + "fontCharacter": "\\E078", "fontColor": "#627379" }, "_rust": { - "fontCharacter": "\\E077", + "fontCharacter": "\\E078", "fontColor": "#6d8086" }, "_salesforce_light": { - "fontCharacter": "\\E078", + "fontCharacter": "\\E079", "fontColor": "#498ba7" }, "_salesforce": { - "fontCharacter": "\\E078", + "fontCharacter": "\\E079", "fontColor": "#519aba" }, "_sass_light": { - "fontCharacter": "\\E079", + "fontCharacter": "\\E07A", "fontColor": "#dd4b78" }, "_sass": { - "fontCharacter": "\\E079", + "fontCharacter": "\\E07A", "fontColor": "#f55385" }, "_sbt_light": { - "fontCharacter": "\\E07A", + "fontCharacter": "\\E07B", "fontColor": "#498ba7" }, "_sbt": { - "fontCharacter": "\\E07A", + "fontCharacter": "\\E07B", "fontColor": "#519aba" }, "_scala_light": { - "fontCharacter": "\\E07B", + "fontCharacter": "\\E07C", "fontColor": "#b8383d" }, "_scala": { - "fontCharacter": "\\E07B", + "fontCharacter": "\\E07C", "fontColor": "#cc3e44" }, "_shell_light": { - "fontCharacter": "\\E07E", + "fontCharacter": "\\E07F", "fontColor": "#455155" }, "_shell": { - "fontCharacter": "\\E07E", + "fontCharacter": "\\E07F", "fontColor": "#4d5a5e" }, "_slim_light": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E080", "fontColor": "#cc6d2e" }, "_slim": { - "fontCharacter": "\\E07F", + "fontCharacter": "\\E080", "fontColor": "#e37933" }, "_smarty_light": { - "fontCharacter": "\\E080", + "fontCharacter": "\\E081", "fontColor": "#b7b73b" }, "_smarty": { - "fontCharacter": "\\E080", + "fontCharacter": "\\E081", "fontColor": "#cbcb41" }, "_spring_light": { - "fontCharacter": "\\E081", + "fontCharacter": "\\E082", "fontColor": "#7fae42" }, "_spring": { - "fontCharacter": "\\E081", + "fontCharacter": "\\E082", "fontColor": "#8dc149" }, "_stylelint_light": { - "fontCharacter": "\\E082", + "fontCharacter": "\\E083", "fontColor": "#bfc2c1" }, "_stylelint": { - "fontCharacter": "\\E082", + "fontCharacter": "\\E083", "fontColor": "#d4d7d6" }, "_stylelint_1_light": { - "fontCharacter": "\\E082", + "fontCharacter": "\\E083", "fontColor": "#455155" }, "_stylelint_1": { - "fontCharacter": "\\E082", + "fontCharacter": "\\E083", "fontColor": "#4d5a5e" }, "_stylus_light": { - "fontCharacter": "\\E083", + "fontCharacter": "\\E084", "fontColor": "#7fae42" }, "_stylus": { - "fontCharacter": "\\E083", + "fontCharacter": "\\E084", "fontColor": "#8dc149" }, "_sublime_light": { - "fontCharacter": "\\E084", + "fontCharacter": "\\E085", "fontColor": "#cc6d2e" }, "_sublime": { - "fontCharacter": "\\E084", + "fontCharacter": "\\E085", "fontColor": "#e37933" }, "_svg_light": { - "fontCharacter": "\\E085", + "fontCharacter": "\\E086", "fontColor": "#9068b0" }, "_svg": { - "fontCharacter": "\\E085", + "fontCharacter": "\\E086", "fontColor": "#a074c4" }, "_svg_1_light": { - "fontCharacter": "\\E085", + "fontCharacter": "\\E086", "fontColor": "#498ba7" }, "_svg_1": { - "fontCharacter": "\\E085", + "fontCharacter": "\\E086", "fontColor": "#519aba" }, "_swift_light": { - "fontCharacter": "\\E086", + "fontCharacter": "\\E087", "fontColor": "#cc6d2e" }, "_swift": { - "fontCharacter": "\\E086", + "fontCharacter": "\\E087", "fontColor": "#e37933" }, "_terraform_light": { - "fontCharacter": "\\E087", + "fontCharacter": "\\E088", "fontColor": "#9068b0" }, "_terraform": { - "fontCharacter": "\\E087", + "fontCharacter": "\\E088", "fontColor": "#a074c4" }, "_tex_light": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#498ba7" }, "_tex": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#519aba" }, "_tex_1_light": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#b7b73b" }, "_tex_1": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#cbcb41" }, "_tex_2_light": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#cc6d2e" }, "_tex_2": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#e37933" }, "_tex_3_light": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#bfc2c1" }, "_tex_3": { - "fontCharacter": "\\E088", + "fontCharacter": "\\E089", "fontColor": "#d4d7d6" }, "_todo": { - "fontCharacter": "\\E08A" + "fontCharacter": "\\E08B" }, "_tsconfig_light": { - "fontCharacter": "\\E08B", + "fontCharacter": "\\E08C", "fontColor": "#498ba7" }, "_tsconfig": { - "fontCharacter": "\\E08B", + "fontCharacter": "\\E08C", "fontColor": "#519aba" }, "_twig_light": { - "fontCharacter": "\\E08C", + "fontCharacter": "\\E08D", "fontColor": "#7fae42" }, "_twig": { - "fontCharacter": "\\E08C", + "fontCharacter": "\\E08D", "fontColor": "#8dc149" }, "_typescript_light": { - "fontCharacter": "\\E08D", + "fontCharacter": "\\E08E", "fontColor": "#498ba7" }, "_typescript": { - "fontCharacter": "\\E08D", + "fontCharacter": "\\E08E", "fontColor": "#519aba" }, "_typescript_1_light": { - "fontCharacter": "\\E08D", + "fontCharacter": "\\E08E", "fontColor": "#b7b73b" }, "_typescript_1": { - "fontCharacter": "\\E08D", + "fontCharacter": "\\E08E", "fontColor": "#cbcb41" }, "_vala_light": { - "fontCharacter": "\\E08E", + "fontCharacter": "\\E08F", "fontColor": "#627379" }, "_vala": { - "fontCharacter": "\\E08E", + "fontCharacter": "\\E08F", "fontColor": "#6d8086" }, "_video_light": { - "fontCharacter": "\\E08F", + "fontCharacter": "\\E090", "fontColor": "#dd4b78" }, "_video": { - "fontCharacter": "\\E08F", + "fontCharacter": "\\E090", "fontColor": "#f55385" }, "_vue_light": { - "fontCharacter": "\\E090", + "fontCharacter": "\\E091", "fontColor": "#7fae42" }, "_vue": { - "fontCharacter": "\\E090", + "fontCharacter": "\\E091", "fontColor": "#8dc149" }, "_wasm_light": { - "fontCharacter": "\\E091", + "fontCharacter": "\\E092", "fontColor": "#9068b0" }, "_wasm": { - "fontCharacter": "\\E091", + "fontCharacter": "\\E092", "fontColor": "#a074c4" }, "_wat_light": { - "fontCharacter": "\\E092", + "fontCharacter": "\\E093", "fontColor": "#9068b0" }, "_wat": { - "fontCharacter": "\\E092", + "fontCharacter": "\\E093", "fontColor": "#a074c4" }, "_webpack_light": { - "fontCharacter": "\\E093", + "fontCharacter": "\\E094", "fontColor": "#498ba7" }, "_webpack": { - "fontCharacter": "\\E093", + "fontCharacter": "\\E094", "fontColor": "#519aba" }, "_wgt_light": { - "fontCharacter": "\\E094", + "fontCharacter": "\\E095", "fontColor": "#498ba7" }, "_wgt": { - "fontCharacter": "\\E094", + "fontCharacter": "\\E095", "fontColor": "#519aba" }, "_windows_light": { - "fontCharacter": "\\E095", + "fontCharacter": "\\E096", "fontColor": "#498ba7" }, "_windows": { - "fontCharacter": "\\E095", + "fontCharacter": "\\E096", "fontColor": "#519aba" }, "_word_light": { - "fontCharacter": "\\E096", + "fontCharacter": "\\E097", "fontColor": "#498ba7" }, "_word": { - "fontCharacter": "\\E096", + "fontCharacter": "\\E097", "fontColor": "#519aba" }, "_xls_light": { - "fontCharacter": "\\E097", + "fontCharacter": "\\E098", "fontColor": "#7fae42" }, "_xls": { - "fontCharacter": "\\E097", + "fontCharacter": "\\E098", "fontColor": "#8dc149" }, "_xml_light": { - "fontCharacter": "\\E098", + "fontCharacter": "\\E099", "fontColor": "#cc6d2e" }, "_xml": { - "fontCharacter": "\\E098", + "fontCharacter": "\\E099", "fontColor": "#e37933" }, "_yarn_light": { - "fontCharacter": "\\E099", + "fontCharacter": "\\E09A", "fontColor": "#498ba7" }, "_yarn": { - "fontCharacter": "\\E099", + "fontCharacter": "\\E09A", "fontColor": "#519aba" }, "_yml_light": { - "fontCharacter": "\\E09A", + "fontCharacter": "\\E09B", "fontColor": "#9068b0" }, "_yml": { - "fontCharacter": "\\E09A", + "fontCharacter": "\\E09B", "fontColor": "#a074c4" }, "_zip_light": { - "fontCharacter": "\\E09B", + "fontCharacter": "\\E09C", "fontColor": "#b8383d" }, "_zip": { - "fontCharacter": "\\E09B", + "fontCharacter": "\\E09C", "fontColor": "#cc3e44" }, "_zip_1_light": { - "fontCharacter": "\\E09B", + "fontCharacter": "\\E09C", "fontColor": "#627379" }, "_zip_1": { - "fontCharacter": "\\E09B", + "fontCharacter": "\\E09C", "fontColor": "#6d8086" } }, @@ -1384,6 +1406,7 @@ "hh": "_cpp_1", "hpp": "_cpp_1", "hxx": "_cpp_1", + "h++": "_cpp_1", "edn": "_clojure_1", "cfc": "_coldfusion", "cfm": "_coldfusion", @@ -1400,6 +1423,9 @@ "csv": "_csv", "xls": "_xls", "xlsx": "_xls", + "cu": "_cu", + "cuh": "_cu_1", + "hu": "_cu_1", "cake": "_cake", "ctp": "_cake_php", "d": "_d", @@ -1428,6 +1454,7 @@ "hxs": "_haxe_1", "hxp": "_haxe_2", "hxml": "_haxe_3", + "jade": "_jade", "class": "_java", "classpath": "_java", "properties": "_java", @@ -1449,6 +1476,8 @@ "ad": "_argdown", "mustache": "_mustache", "stache": "_mustache", + "nim": "_nim", + "nims": "_nim", "njk": "_nunjucks", "nunjucks": "_nunjucks", "nunjs": "_nunjucks", @@ -1456,8 +1485,6 @@ "njs": "_nunjucks", "nj": "_nunjucks", "npm-debug.log": "_npm", - "npmignore": "_npm_1", - "npmrc": "_npm_1", "ml": "_ocaml", "mli": "_ocaml", "cmx": "_ocaml", @@ -1467,7 +1494,6 @@ "pddl": "_pddl", "plan": "_plan", "happenings": "_happenings", - "pug": "_pug", "pp": "_puppet", "epp": "_puppet", "spec.jsx": "_react_1", @@ -1485,6 +1511,7 @@ "springbeans": "_spring", "slim": "_slim", "smarty.tpl": "_smarty", + "tpl": "_smarty", "sbt": "_sbt", "scala": "_scala", "sol": "_ethereum", @@ -1523,6 +1550,8 @@ "pxm": "_image", "svg": "_svg", "svgx": "_image", + "tiff": "_image", + "webp": "_image", "sublime-project": "_sublime", "sublime-workspace": "_sublime", "component": "_salesforce", @@ -1642,11 +1671,13 @@ "csharp": "_c-sharp", "css": "_css", "dockerfile": "_docker", + "ignore": "_npm_1", "fsharp": "_f-sharp", "go": "_go2", "groovy": "_grails", "handlebars": "_mustache", "html": "_html_3", + "properties": "_npm_1", "java": "_java", "javascriptreact": "_react", "javascript": "_javascript", @@ -1660,7 +1691,7 @@ "perl": "_perl", "php": "_php", "powershell": "_powershell", - "jade": "_jade", + "jade": "_pug", "python": "_python", "r": "_R", "razor": "_html", @@ -1712,6 +1743,7 @@ "hh": "_cpp_1_light", "hpp": "_cpp_1_light", "hxx": "_cpp_1_light", + "h++": "_cpp_1_light", "edn": "_clojure_1_light", "cfc": "_coldfusion_light", "cfm": "_coldfusion_light", @@ -1728,6 +1760,9 @@ "csv": "_csv_light", "xls": "_xls_light", "xlsx": "_xls_light", + "cu": "_cu_light", + "cuh": "_cu_1_light", + "hu": "_cu_1_light", "cake": "_cake_light", "ctp": "_cake_php_light", "d": "_d_light", @@ -1756,6 +1791,7 @@ "hxs": "_haxe_1_light", "hxp": "_haxe_2_light", "hxml": "_haxe_3_light", + "jade": "_jade_light", "class": "_java_light", "classpath": "_java_light", "properties": "_java_light", @@ -1777,6 +1813,8 @@ "ad": "_argdown_light", "mustache": "_mustache_light", "stache": "_mustache_light", + "nim": "_nim_light", + "nims": "_nim_light", "njk": "_nunjucks_light", "nunjucks": "_nunjucks_light", "nunjs": "_nunjucks_light", @@ -1784,8 +1822,6 @@ "njs": "_nunjucks_light", "nj": "_nunjucks_light", "npm-debug.log": "_npm_light", - "npmignore": "_npm_1_light", - "npmrc": "_npm_1_light", "ml": "_ocaml_light", "mli": "_ocaml_light", "cmx": "_ocaml_light", @@ -1795,7 +1831,6 @@ "pddl": "_pddl_light", "plan": "_plan_light", "happenings": "_happenings_light", - "pug": "_pug_light", "pp": "_puppet_light", "epp": "_puppet_light", "spec.jsx": "_react_1_light", @@ -1813,6 +1848,7 @@ "springbeans": "_spring_light", "slim": "_slim_light", "smarty.tpl": "_smarty_light", + "tpl": "_smarty_light", "sbt": "_sbt_light", "scala": "_scala_light", "sol": "_ethereum_light", @@ -1851,6 +1887,8 @@ "pxm": "_image_light", "svg": "_svg_light", "svgx": "_image_light", + "tiff": "_image_light", + "webp": "_image_light", "sublime-project": "_sublime_light", "sublime-workspace": "_sublime_light", "component": "_salesforce_light", @@ -1913,11 +1951,13 @@ "csharp": "_c-sharp_light", "css": "_css_light", "dockerfile": "_docker_light", + "ignore": "_npm_1_light", "fsharp": "_f-sharp_light", "go": "_go2_light", "groovy": "_grails_light", "handlebars": "_mustache_light", "html": "_html_3_light", + "properties": "_npm_1_light", "java": "_java_light", "javascriptreact": "_react_light", "javascript": "_javascript_light", @@ -1931,7 +1971,7 @@ "perl": "_perl_light", "php": "_php_light", "powershell": "_powershell_light", - "jade": "_jade_light", + "jade": "_pug_light", "python": "_python_light", "r": "_R_light", "razor": "_html_light", @@ -2024,5 +2064,5 @@ "npm-debug.log": "_npm_ignored_light" } }, - "version": "https://github.com/jesseweed/seti-ui/commit/f3b2775662b0075aab56e5f0c03269f21f3f0f30" + "version": "https://github.com/jesseweed/seti-ui/commit/719e5d384e878b0e190abc80247a8726f083a393" } \ No newline at end of file From 2416082d2d72559c70792920ff3886942ceef407 Mon Sep 17 00:00:00 2001 From: Caio Date: Wed, 12 Aug 2020 19:41:41 -0300 Subject: [PATCH 03/98] revert seti-ui update but leave h++-specific icons --- extensions/theme-seti/cgmanifest.json | 2 +- extensions/theme-seti/icons/seti.woff | Bin 35272 -> 34972 bytes .../theme-seti/icons/vs-seti-icon-theme.json | 618 ++++++++---------- 3 files changed, 291 insertions(+), 329 deletions(-) diff --git a/extensions/theme-seti/cgmanifest.json b/extensions/theme-seti/cgmanifest.json index 8899dae032b..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": "719e5d384e878b0e190abc80247a8726f083a393" + "commitHash": "f3b2775662b0075aab56e5f0c03269f21f3f0f30" } }, "version": "0.1.0" diff --git a/extensions/theme-seti/icons/seti.woff b/extensions/theme-seti/icons/seti.woff index a7c47a3ce0c5aa65cdf6c6f79e8b49c630216529..5dc3bb8d9b0386a5cd2b60a122305f7040296dac 100644 GIT binary patch delta 34667 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 DfDDbM delta 35003 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 Date: Thu, 13 Aug 2020 08:04:42 -0300 Subject: [PATCH 04/98] remove .h++-specific icons --- extensions/theme-seti/icons/vs-seti-icon-theme.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index 21f9f276feb..a1f5817da5c 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -1384,7 +1384,6 @@ "hh": "_cpp_1", "hpp": "_cpp_1", "hxx": "_cpp_1", - "h++": "_cpp_1", "edn": "_clojure_1", "cfc": "_coldfusion", "cfm": "_coldfusion", @@ -1713,7 +1712,6 @@ "hh": "_cpp_1_light", "hpp": "_cpp_1_light", "hxx": "_cpp_1_light", - "h++": "_cpp_1_light", "edn": "_clojure_1_light", "cfc": "_coldfusion_light", "cfm": "_coldfusion_light", From c45e05e4a659b72e61b66f7fa0d0630794d533bc Mon Sep 17 00:00:00 2001 From: Caio <39964829+amazingcaio@users.noreply.github.com> Date: Mon, 17 Aug 2020 21:40:18 -0300 Subject: [PATCH 05/98] treat *.c++ and *.h++ files as c++ on macos --- build/lib/electron.js | 2 +- build/lib/electron.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/lib/electron.js b/build/lib/electron.js index bb71f14c12d..71c25398a50 100644 --- a/build/lib/electron.js +++ b/build/lib/electron.js @@ -41,7 +41,7 @@ exports.config = { darwinBundleDocumentType(["bowerrc"], 'resources/darwin/bower.icns'), darwinBundleDocumentType(["c", "h"], 'resources/darwin/c.icns'), darwinBundleDocumentType(["config", "editorconfig", "gitattributes", "gitconfig", "gitignore", "ini"], 'resources/darwin/config.icns'), - darwinBundleDocumentType(["cc", "cpp", "cxx", "hh", "hpp", "hxx"], 'resources/darwin/cpp.icns'), + darwinBundleDocumentType(["cc", "cpp", "cxx", "c++", "hh", "hpp", "hxx", "h++"], 'resources/darwin/cpp.icns'), darwinBundleDocumentType(["cs", "csx"], 'resources/darwin/csharp.icns'), darwinBundleDocumentType(["css"], 'resources/darwin/css.icns'), darwinBundleDocumentType(["go"], 'resources/darwin/go.icns'), diff --git a/build/lib/electron.ts b/build/lib/electron.ts index e0beca78079..c761cdfa083 100644 --- a/build/lib/electron.ts +++ b/build/lib/electron.ts @@ -46,7 +46,7 @@ export const config = { darwinBundleDocumentType(["bowerrc"], 'resources/darwin/bower.icns'), darwinBundleDocumentType(["c", "h"], 'resources/darwin/c.icns'), darwinBundleDocumentType(["config", "editorconfig", "gitattributes", "gitconfig", "gitignore", "ini"], 'resources/darwin/config.icns'), - darwinBundleDocumentType(["cc", "cpp", "cxx", "hh", "hpp", "hxx"], 'resources/darwin/cpp.icns'), + darwinBundleDocumentType(["cc", "cpp", "cxx", "c++", "hh", "hpp", "hxx", "h++"], 'resources/darwin/cpp.icns'), darwinBundleDocumentType(["cs", "csx"], 'resources/darwin/csharp.icns'), darwinBundleDocumentType(["css"], 'resources/darwin/css.icns'), darwinBundleDocumentType(["go"], 'resources/darwin/go.icns'), From 602baedf1c729ac54eb35b0cd5de2625e212c3c1 Mon Sep 17 00:00:00 2001 From: Nicolas Vuillamy Date: Thu, 3 Sep 2020 10:25:57 +0200 Subject: [PATCH 06/98] Add .nf extension to Groovy file extensions Closes #106017 : https://github.com/microsoft/vscode/issues/106017 --- extensions/groovy/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/groovy/package.json b/extensions/groovy/package.json index ab2ef0da7ba..f3a0cc17ec8 100644 --- a/extensions/groovy/package.json +++ b/extensions/groovy/package.json @@ -13,7 +13,7 @@ "languages": [{ "id": "groovy", "aliases": ["Groovy", "groovy"], - "extensions": [".groovy", ".gvy", ".gradle", ".jenkinsfile"], + "extensions": [".groovy", ".gvy", ".gradle", ".jenkinsfile", ".nf"], "filenamePatterns": ["Jenkinsfile.*"], "firstLine": "^#!.*\\bgroovy\\b", "configuration": "./language-configuration.json" From 11158cc1d1301b8a5e9f9ea9c5ed3d4062124e7f Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Sep 2020 20:28:28 -0700 Subject: [PATCH 07/98] re #105735. selections as NotebookEditor properties. --- .../api/browser/mainThreadNotebook.ts | 19 ++++++++++--------- .../workbench/api/common/extHost.protocol.ts | 2 +- .../workbench/api/common/extHostNotebook.ts | 17 ++++++++--------- .../notebook/browser/notebookBrowser.ts | 1 + .../notebook/browser/notebookEditorWidget.ts | 11 +++++++++++ .../browser/viewModel/notebookViewModel.ts | 1 - .../common/model/notebookTextModel.ts | 13 ------------- .../contrib/notebook/common/notebookCommon.ts | 2 ++ .../notebook/test/testNotebookEditor.ts | 4 ++++ 9 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index d144bec6070..afd3c5345f2 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -58,7 +58,7 @@ class DocumentAndEditorState { const apiEditors = []; for (let id in after.textEditors) { const editor = after.textEditors.get(id)!; - apiEditors.push({ id, documentUri: editor.uri!, selections: editor!.textModel!.selections, visibleRanges: editor.visibleRanges }); + apiEditors.push({ id, documentUri: editor.uri!, selections: editor!.getSelectionHandles(), visibleRanges: editor.visibleRanges }); } return { @@ -72,7 +72,7 @@ class DocumentAndEditorState { const addedAPIEditors = editorDelta.added.map(add => ({ id: add.getId(), documentUri: add.uri!, - selections: add.textModel!.selections || [], + selections: add.getSelectionHandles(), visibleRanges: add.visibleRanges })); @@ -231,7 +231,12 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo if (!this._editorEventListenersMapping.has(editor.getId())) { const disposableStore = new DisposableStore(); disposableStore.add(editor.onDidChangeVisibleRanges(() => { - this._proxy.$acceptEditorPropertiesChanged(editor.getId(), { visibleRanges: { ranges: editor.visibleRanges } }); + this._proxy.$acceptEditorPropertiesChanged(editor.getId(), { visibleRanges: { ranges: editor.visibleRanges }, selections: null }); + })); + + disposableStore.add(editor.onDidChangeSelection(() => { + const selectionHandles = editor.getSelectionHandles(); + this._proxy.$acceptEditorPropertiesChanged(editor.getId(), { visibleRanges: null, selections: { selections: selectionHandles } }); })); this._editorEventListenersMapping.set(editor.getId(), disposableStore); @@ -262,11 +267,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo const textModel = this._notebookService.getNotebookTextModel(doc); disposableStore.add(textModel!.onDidModelChangeProxy(e => { this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty); - this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: { selections: textModel!.selections }, metadata: null }); - })); - disposableStore.add(textModel!.onDidSelectionChange(e => { - const selectionsChange = e ? { selections: e } : null; - this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: selectionsChange, metadata: null }); + this._proxy.$acceptDocumentPropertiesChanged(doc, { metadata: null }); })); this._editorEventListenersMapping.set(textModel!.uri.toString(), disposableStore); @@ -448,7 +449,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo textModel.insertTemplateCell(mainCell); } - this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { selections: null, metadata: textModel.metadata }); + this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { metadata: textModel.metadata }); return; }, resolveNotebookEditor: async (viewType: string, uri: URI, editorId: string) => { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 4b794666295..1f3a03d8a5b 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1639,11 +1639,11 @@ export interface INotebookVisibleRangesEvent { export interface INotebookEditorPropertiesChangeData { visibleRanges: INotebookVisibleRangesEvent | null; + selections: INotebookSelectionChangeEvent | null; } export interface INotebookDocumentPropertiesChangeData { metadata: NotebookDocumentMetadata | null; - selections: INotebookSelectionChangeEvent | null; } export interface INotebookModelAddedData { diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 2cd2da1b021..0c4bf7c66aa 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -1315,15 +1315,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN visibleRanges: editor.editor.visibleRanges }); } - } - - $acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void { - this.logService.debug('ExtHostNotebook#$acceptDocumentPropertiesChanged', uriComponents.path, data); - const editor = this._getEditorFromURI(uriComponents); - - if (!editor) { - return; - } if (data.selections) { if (data.selections.selections.length) { @@ -1338,7 +1329,15 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN selection: editor.editor.selection }); } + } + $acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void { + this.logService.debug('ExtHostNotebook#$acceptDocumentPropertiesChanged', uriComponents.path, data); + const editor = this._getEditorFromURI(uriComponents); + + if (!editor) { + return; + } if (data.metadata) { editor.editor.notebookData.notebookDocument.metadata = { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 5cc672c00e1..0c49b446411 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -233,6 +233,7 @@ export interface INotebookEditor extends IEditor { getDomNode(): HTMLElement; getOverflowContainerDomNode(): HTMLElement; getInnerWebview(): Webview | undefined; + getSelectionHandles(): number[]; /** * Focus the notebook editor cell list diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b2588dd631b..d6b3bdc6066 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -215,6 +215,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._cursorNavigationMode = v; } + private readonly _onDidChangeSelection = this._register(new Emitter()); + get onDidChangeSelection(): Event { return this._onDidChangeSelection.event; } + private readonly _onDidChangeVisibleRanges = this._register(new Emitter()); onDidChangeVisibleRanges: Event = this._onDidChangeVisibleRanges.event; @@ -268,6 +271,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return this._uuid; } + getSelectionHandles(): number[] { + return this.viewModel?.selectionHandles || []; + } + hasModel() { return !!this._notebookViewModel; } @@ -933,6 +940,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } } + this._localStore.add(this.viewModel.onDidChangeSelection(() => { + this._onDidChangeSelection.fire(); + })); + this._localStore.add(this._list!.onWillScroll(e => { this._onWillScroll.fire(e); if (!this._webviewResolved) { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index b06cb8d453a..15d2b30af18 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -218,7 +218,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD } this._selections = selections; - this._notebook.selections = selections; this._onDidChangeSelection.fire(); } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 805c8bb61a6..10e19185977 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -118,8 +118,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel get emitSelections() { return this._emitSelections.event; } private _onDidModelChangeProxy = this._register(new Emitter()); get onDidModelChangeProxy(): Event { return this._onDidModelChangeProxy.event; } - private _onDidSelectionChangeProxy = this._register(new Emitter()); - get onDidSelectionChange(): Event { return this._onDidSelectionChangeProxy.event; } private _onDidChangeContent = this._register(new Emitter()); onDidChangeContent: Event = this._onDidChangeContent.event; private _onDidChangeMetadata = this._register(new Emitter()); @@ -151,17 +149,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return this._versionId; } - private _selections: number[] = []; - - get selections() { - return this._selections; - } - - set selections(selections: number[]) { - this._selections = selections; - this._onDidSelectionChangeProxy.fire(this._selections); - } - private _dirty = false; protected readonly _onDidChangeDirty = this._register(new Emitter()); readonly onDidChangeDirty = this._onDidChangeDirty.event; diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index b8753742ac4..e13425768bf 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -688,6 +688,8 @@ export interface IEditor extends editorCommon.ICompositeCodeEditor { readonly onDidChangeModel: Event; readonly onDidFocusEditorWidget: Event; readonly onDidChangeVisibleRanges: Event; + readonly onDidChangeSelection: Event; + getSelectionHandles(): number[]; isNotebookEditor: boolean; visibleRanges: ICellRange[]; uri?: URI; diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 33146612f34..6872b80d42b 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -66,6 +66,9 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + getSelectionHandles(): number[] { + return []; + } setOptions(options: NotebookEditorOptions | undefined): Promise { @@ -82,6 +85,7 @@ export class TestNotebookEditor implements INotebookEditor { onDidScroll = new Emitter().event; onWillDispose = new Emitter().event; onDidChangeVisibleRanges: Event = new Emitter().event; + onDidChangeSelection: Event = new Emitter().event; visibleRanges: ICellRange[] = []; uri?: URI | undefined; textModel?: NotebookTextModel | undefined; From a44751de538aa3f696be3232d7fca586acc80118 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Sep 2020 20:32:03 -0700 Subject: [PATCH 08/98] re #105735. content changes on text model should always be emitted to ext host. --- .../common/model/notebookTextModel.ts | 53 ++++++++----------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 10e19185977..f1d0dcaa0a4 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -423,7 +423,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } - insertNewCell(index: number, cells: NotebookCellTextModel[], emitToExtHost: boolean = true): void { + insertNewCell(index: number, cells: NotebookCellTextModel[]): void { this._isUntitled = false; for (let i = 0; i < cells.length; i++) { @@ -443,31 +443,29 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._increaseVersionId(); - if (emitToExtHost) { - this._onDidModelChangeProxy.fire({ - kind: NotebookCellsChangeType.ModelChange, - versionId: this._versionId, changes: - [[ - index, - 0, - cells.map(cell => ({ - handle: cell.handle, - uri: cell.uri, - source: cell.textBuffer.getLinesContent(), - eol: cell.textBuffer.getEOL(), - language: cell.language, - cellKind: cell.cellKind, - outputs: cell.outputs, - metadata: cell.metadata - })) - ]] - }); - } + this._onDidModelChangeProxy.fire({ + kind: NotebookCellsChangeType.ModelChange, + versionId: this._versionId, changes: + [[ + index, + 0, + cells.map(cell => ({ + handle: cell.handle, + uri: cell.uri, + source: cell.textBuffer.getLinesContent(), + eol: cell.textBuffer.getEOL(), + language: cell.language, + cellKind: cell.cellKind, + outputs: cell.outputs, + metadata: cell.metadata + })) + ]] + }); return; } - removeCell(index: number, count: number, emitToExtHost: boolean = true) { + removeCell(index: number, count: number) { this._isUntitled = false; for (let i = index; i < index + count; i++) { @@ -480,12 +478,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidChangeContent.fire(); this._increaseVersionId(); - if (emitToExtHost) { - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]] }); - } + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]] }); } - moveCellToIdx(index: number, length: number, newIdx: number, emitToExtHost: boolean = true) { + moveCellToIdx(index: number, length: number, newIdx: number) { this.assertIndex(index); this.assertIndex(newIdx); @@ -495,10 +491,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidChangeContent.fire(); this._increaseVersionId(); - - if (emitToExtHost) { - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, newIdx }); - } + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, newIdx }); } assertIndex(index: number) { From 759ead4d71ebc9fe02bf1a02f24dfc648b3ca281 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Sep 2020 21:22:18 -0700 Subject: [PATCH 09/98] remove onDidChangeMetadata. --- .../workbench/api/common/extHostNotebook.ts | 2 +- .../browser/viewModel/notebookViewModel.ts | 8 +++-- .../common/model/notebookTextModel.ts | 32 +++++++++---------- .../contrib/notebook/common/notebookCommon.ts | 21 +++++++++--- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 0c4bf7c66aa..dc1c5fa374a 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -333,7 +333,7 @@ export class ExtHostNotebookDocument extends Disposable { this._clearAllCellOutputs(); } else if (event.kind === NotebookCellsChangeType.ChangeLanguage) { this._changeCellLanguage(event.index, event.language); - } else if (event.kind === NotebookCellsChangeType.ChangeMetadata) { + } else if (event.kind === NotebookCellsChangeType.ChangeCellMetadata) { this._changeCellMetadata(event.index, event.metadata); } } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 15d2b30af18..87bf0ef6e87 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -23,7 +23,7 @@ import { NotebookEventDispatcher, NotebookMetadataChangedEvent } from 'vs/workbe import { CellFoldingState, EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; -import { CellKind, NotebookCellMetadata, INotebookSearchOptions, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, NotebookCellMetadata, INotebookSearchOptions, ICellRange, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { FoldingRegions } from 'vs/editor/contrib/folding/foldingRanges'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer'; @@ -308,8 +308,10 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD this.selectionHandles = endSelectionHandles; })); - this._register(this._notebook.onDidChangeMetadata(e => { - this.eventDispatcher.emit([new NotebookMetadataChangedEvent(e)]); + this._register(this._notebook.onDidChangeContent(e => { + if (e === NotebookCellsChangeType.ChangeDocumentMetadata) { + this.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]); + } })); this._register(this._notebook.emitSelections(selections => { diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index f1d0dcaa0a4..93d0a344a69 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -118,10 +118,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel get emitSelections() { return this._emitSelections.event; } private _onDidModelChangeProxy = this._register(new Emitter()); get onDidModelChangeProxy(): Event { return this._onDidModelChangeProxy.event; } - private _onDidChangeContent = this._register(new Emitter()); - onDidChangeContent: Event = this._onDidChangeContent.event; - private _onDidChangeMetadata = this._register(new Emitter()); - onDidChangeMetadata: Event = this._onDidChangeMetadata.event; + private _onDidChangeContent = this._register(new Emitter()); + onDidChangeContent: Event = this._onDidChangeContent.event; private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); cells: NotebookCellTextModel[]; @@ -210,7 +208,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = mainCells[i].onDidChangeContent(() => { this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); }); this._cellListeners.set(mainCells[i].handle, dirtyStateListener); @@ -324,7 +322,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = cell.onDidChangeContent(() => { this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); }); this._cellListeners.set(cell.handle, dirtyStateListener); this._mapping.set(cell.handle, cell); @@ -335,7 +333,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.cells.splice(index, count, ...cells); this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); } handleEdit(label: string | undefined, undo: () => void, redo: () => void): void { @@ -378,7 +376,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel updateNotebookMetadata(metadata: NotebookDocumentMetadata) { this.metadata = metadata; - this._onDidChangeMetadata.fire(this.metadata); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeDocumentMetadata); } insertTemplateCell(cell: NotebookCellTextModel) { @@ -394,12 +392,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._isUntitled = false; this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); }); this._cellListeners.set(cell.handle, dirtyStateListener); this.setDirty(false); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, @@ -431,7 +429,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = cells[i].onDidChangeContent(() => { this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); }); this._cellListeners.set(cells[i].handle, dirtyStateListener); @@ -439,7 +437,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.cells.splice(index, 0, ...cells); this.setDirty(true); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._increaseVersionId(); @@ -475,7 +473,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } this.cells.splice(index, count); this.setDirty(true); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._increaseVersionId(); this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]] }); @@ -488,7 +486,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const cells = this.cells.splice(index, length); this.cells.splice(newIdx, 0, ...cells); this.setDirty(true); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.Move); this._increaseVersionId(); this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, newIdx }); @@ -510,7 +508,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel if (!this.transientOptions.transientOutputs) { this._increaseVersionId(); this.setDirty(true); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.Output); } this._onDidModelChangeProxy.fire({ @@ -585,13 +583,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } cell.metadata = metadata; this.setDirty(true); - this._onDidChangeContent.fire(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellMetadata); } else { cell.metadata = metadata; } this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata }); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata }); } deltaCellMetadata(handle: number, newMetadata: NotebookCellMetadata) { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index e13425768bf..b598294f6c9 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -278,7 +278,7 @@ export interface INotebookTextModel { languages: string[]; cells: ICell[]; onDidChangeCells?: Event<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>; - onDidChangeContent: Event; + onDidChangeContent: Event; onWillDispose(listener: () => void): IDisposable; } @@ -348,8 +348,10 @@ export enum NotebookCellsChangeType { CellsClearOutput = 4, ChangeLanguage = 5, Initialize = 6, - ChangeMetadata = 7, + ChangeCellMetadata = 7, Output = 8, + ChangeCellContent = 9, + ChangeDocumentMetadata = 10 } export interface NotebookCellsInitializeEvent { @@ -358,6 +360,11 @@ export interface NotebookCellsInitializeEvent { readonly versionId: number; } +export interface NotebookCellContentChangeEvent { + readonly kind: NotebookCellsChangeType.ChangeCellContent; + readonly versionId: number; +} + export interface NotebookCellsModelChangedEvent { readonly kind: NotebookCellsChangeType.ModelChange; readonly changes: NotebookCellsSplice2[]; @@ -397,13 +404,19 @@ export interface NotebookCellsChangeLanguageEvent { } export interface NotebookCellsChangeMetadataEvent { - readonly kind: NotebookCellsChangeType.ChangeMetadata; + readonly kind: NotebookCellsChangeType.ChangeCellMetadata; readonly versionId: number; readonly index: number; readonly metadata: NotebookCellMetadata | undefined; } -export type NotebookCellsChangedEvent = NotebookCellsInitializeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellClearOutputEvent | NotebookCellsClearOutputEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent; +export interface NotebookDocumentChangeMetadataEvent { + readonly kind: NotebookCellsChangeType.ChangeDocumentMetadata; + readonly versionId: number; + readonly metadata: NotebookDocumentMetadata | undefined; +} + +export type NotebookCellsChangedEvent = NotebookCellsInitializeEvent | NotebookDocumentChangeMetadataEvent | NotebookCellContentChangeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellClearOutputEvent | NotebookCellsClearOutputEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent; export const enum CellEditType { Replace = 1, From 25b2e70d05af044312f7af50a17cb2cdae2dbef1 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Sep 2020 21:33:16 -0700 Subject: [PATCH 10/98] reduce _onDidChangeCells --- .../common/model/notebookTextModel.ts | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 93d0a344a69..245c3bed8d7 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -112,6 +112,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel private readonly _onWillDispose: Emitter = this._register(new Emitter()); readonly onWillDispose: Event = this._onWillDispose.event; + private _dirty = false; + protected readonly _onDidChangeDirty = this._register(new Emitter()); + readonly onDidChangeDirty = this._onDidChangeDirty.event; + private readonly _onDidChangeCells = this._register(new Emitter<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>()); get onDidChangeCells() { return this._onDidChangeCells.event; } private readonly _emitSelections = this._register(new Emitter()); @@ -147,10 +151,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return this._versionId; } - private _dirty = false; - protected readonly _onDidChangeDirty = this._register(new Emitter()); - readonly onDidChangeDirty = this._onDidChangeDirty.event; - private _operationManager: NotebookOperationManager; constructor( @@ -421,7 +421,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } - insertNewCell(index: number, cells: NotebookCellTextModel[]): void { + insertNewCell(index: number, cells: NotebookCellTextModel[], synchronous: boolean): void { this._isUntitled = false; for (let i = 0; i < cells.length; i++) { @@ -460,10 +460,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel ]] }); + this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 0, cells]] }); + return; } - removeCell(index: number, count: number) { + removeCell(index: number, count: number, synchronous: boolean) { this._isUntitled = false; for (let i = index; i < index + count; i++) { @@ -477,6 +479,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._increaseVersionId(); this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]] }); + this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); } moveCellToIdx(index: number, length: number, newIdx: number) { @@ -615,13 +618,11 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel //#region Notebook Text Model Edit API private _insertCellDelegate(insertIndex: number, insertCell: NotebookCellTextModel) { - this.insertNewCell(insertIndex, [insertCell]); - this._onDidChangeCells.fire({ synchronous: true, splices: [[insertIndex, 0, [insertCell]]] }); + this.insertNewCell(insertIndex, [insertCell], true); } private _deleteCellDelegate(deleteIndex: number) { - this.removeCell(deleteIndex, 1); - this._onDidChangeCells.fire({ synchronous: true, splices: [[deleteIndex, 1, []]] }); + this.removeCell(deleteIndex, 1, true); } private _emitSelectionsDelegate(selections: number[]) { @@ -640,9 +641,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } - this.insertNewCell(index, [cell]); - - this._onDidChangeCells.fire({ synchronous, splices: [[index, 0, [cell]]] }); + this.insertNewCell(index, [cell], synchronous); if (endSelections) { this._emitSelections.fire(endSelections); @@ -659,8 +658,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }, undefined, undefined)); } - this.insertNewCell(index, [cell]); - this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 0, [cell]]] }); + this.insertNewCell(index, [cell], synchronous); } deleteCell2(index: number, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { @@ -673,8 +671,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }, beforeSelections, endSelections)); } - this.removeCell(index, 1); - this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); + this.removeCell(index, 1, synchronous); if (endSelections) { this._emitSelections.fire(endSelections); } From 6d0783e58e7001fcd32557843667c3896cc48bab Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Sep 2020 21:40:01 -0700 Subject: [PATCH 11/98] inline delegates --- .../common/model/notebookTextModel.ts | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 245c3bed8d7..1adbfdc7505 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -286,9 +286,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }); this._operationManager.pushEditOperation(new SpliceCellsEdit(this.uri, undoDiff, { - insertCell: this._insertCellDelegate.bind(this), - deleteCell: this._deleteCellDelegate.bind(this), - emitSelections: this._emitSelectionsDelegate.bind(this) + insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, + deleteCell: (index) => { this._removeCell(index, 1, true); }, + emitSelections: (selections) => { this._emitSelections.fire(selections); } }, undefined, undefined)); this._onDidChangeCells.fire({ synchronous: synchronous, splices: diffs }); @@ -421,7 +421,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } - insertNewCell(index: number, cells: NotebookCellTextModel[], synchronous: boolean): void { + private _insertNewCell(index: number, cells: NotebookCellTextModel[], synchronous: boolean): void { this._isUntitled = false; for (let i = 0; i < cells.length; i++) { @@ -465,7 +465,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } - removeCell(index: number, count: number, synchronous: boolean) { + private _removeCell(index: number, count: number, synchronous: boolean) { this._isUntitled = false; for (let i = index; i < index + count; i++) { @@ -581,7 +581,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } this.changeCellMetadata(cell.handle, newMetadata, false); }, - emitSelections: this._emitSelectionsDelegate.bind(this) + emitSelections: (selections) => { this._emitSelections.fire(selections); } })); } cell.metadata = metadata; @@ -617,31 +617,19 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel //#region Notebook Text Model Edit API - private _insertCellDelegate(insertIndex: number, insertCell: NotebookCellTextModel) { - this.insertNewCell(insertIndex, [insertCell], true); - } - - private _deleteCellDelegate(deleteIndex: number) { - this.removeCell(deleteIndex, 1, true); - } - - private _emitSelectionsDelegate(selections: number[]) { - this._emitSelections.fire(selections); - } - createCell2(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { const cell = this.createCellTextModel(source, language, type, [], metadata); if (pushUndoStop) { this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { - insertCell: this._insertCellDelegate.bind(this), - deleteCell: this._deleteCellDelegate.bind(this), - emitSelections: this._emitSelectionsDelegate.bind(this) + insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, + deleteCell: (index) => { this._removeCell(index, 1, true); }, + emitSelections: (selections) => { this._emitSelections.fire(selections); } }, beforeSelections, endSelections)); } - this.insertNewCell(index, [cell], synchronous); + this._insertNewCell(index, [cell], synchronous); if (endSelections) { this._emitSelections.fire(endSelections); @@ -652,26 +640,26 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel insertCell2(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean): void { if (pushUndoStop) { this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { - insertCell: this._insertCellDelegate.bind(this), - deleteCell: this._deleteCellDelegate.bind(this), - emitSelections: this._emitSelectionsDelegate.bind(this) + insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, + deleteCell: (index) => { this._removeCell(index, 1, true); }, + emitSelections: (selections) => { this._emitSelections.fire(selections); } }, undefined, undefined)); } - this.insertNewCell(index, [cell], synchronous); + this._insertNewCell(index, [cell], synchronous); } deleteCell2(index: number, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { const cell = this.cells[index]; if (pushUndoStop) { this._operationManager.pushEditOperation(new DeleteCellEdit(this.uri, index, cell, { - insertCell: this._insertCellDelegate.bind(this), - deleteCell: this._deleteCellDelegate.bind(this), - emitSelections: this._emitSelectionsDelegate.bind(this) + insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, + deleteCell: (index) => { this._removeCell(index, 1, true); }, + emitSelections: (selections) => { this._emitSelections.fire(selections); } }, beforeSelections, endSelections)); } - this.removeCell(index, 1, synchronous); + this._removeCell(index, 1, synchronous); if (endSelections) { this._emitSelections.fire(endSelections); } @@ -684,7 +672,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel moveCell: (fromIndex: number, length: number, toIndex: number, beforeSelections: number[] | undefined, endSelections: number[] | undefined) => { this.moveCellToIdx2(fromIndex, length, toIndex, true, false, beforeSelections, endSelections); }, - emitSelections: this._emitSelectionsDelegate.bind(this) + emitSelections: (selections) => { this._emitSelections.fire(selections); } }, beforeSelections, endSelections)); } From 00a0e836f5547acfc68c9bc0a04ca79f088aa99b Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 3 Sep 2020 21:41:58 -0700 Subject: [PATCH 12/98] no more *2 API --- .../common/model/notebookTextModel.ts | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 1adbfdc7505..dbf710470ef 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -482,19 +482,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); } - moveCellToIdx(index: number, length: number, newIdx: number) { - this.assertIndex(index); - this.assertIndex(newIdx); - - const cells = this.cells.splice(index, length); - this.cells.splice(newIdx, 0, ...cells); - this.setDirty(true); - this._onDidChangeContent.fire(NotebookCellsChangeType.Move); - - this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, newIdx }); - } - assertIndex(index: number) { if (index < 0 || index >= this.cells.length) { throw new Error(`model index out of range ${index}`); @@ -617,7 +604,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel //#region Notebook Text Model Edit API - createCell2(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { + createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { const cell = this.createCellTextModel(source, language, type, [], metadata); if (pushUndoStop) { @@ -637,7 +624,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return cell; } - insertCell2(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean): void { + insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean): void { if (pushUndoStop) { this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, @@ -649,7 +636,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._insertNewCell(index, [cell], synchronous); } - deleteCell2(index: number, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { + deleteCell(index: number, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { const cell = this.cells[index]; if (pushUndoStop) { this._operationManager.pushEditOperation(new DeleteCellEdit(this.uri, index, cell, { @@ -665,18 +652,30 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } } - moveCellToIdx2(index: number, length: number, newIdx: number, synchronous: boolean, pushedToUndoStack: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): boolean { + moveCellToIdx(index: number, length: number, newIdx: number, synchronous: boolean, pushedToUndoStack: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): boolean { const cells = this.cells.slice(index, index + length); if (pushedToUndoStack) { this._operationManager.pushEditOperation(new MoveCellEdit(this.uri, index, length, newIdx, { moveCell: (fromIndex: number, length: number, toIndex: number, beforeSelections: number[] | undefined, endSelections: number[] | undefined) => { - this.moveCellToIdx2(fromIndex, length, toIndex, true, false, beforeSelections, endSelections); + this.moveCellToIdx(fromIndex, length, toIndex, true, false, beforeSelections, endSelections); }, emitSelections: (selections) => { this._emitSelections.fire(selections); } }, beforeSelections, endSelections)); } - this.moveCellToIdx(index, length, newIdx); + this.assertIndex(index); + this.assertIndex(newIdx); + + { + const cells = this.cells.splice(index, length); + this.cells.splice(newIdx, 0, ...cells); + this.setDirty(true); + this._onDidChangeContent.fire(NotebookCellsChangeType.Move); + + this._increaseVersionId(); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, newIdx }); + } + // todo, we can't emit this change as it will create a new view model and that will hold // a new reference to the document, thus this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, length, []]] }); @@ -706,7 +705,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel let insertIndex = index + 1; const newCells = []; for (let j = 1; j < newLinesContents.length; j++, insertIndex++) { - newCells.push(this.createCell2(insertIndex, newLinesContents[j], language, kind, undefined, true, false, undefined, undefined)); + newCells.push(this.createCell(insertIndex, newLinesContents[j], language, kind, undefined, true, false, undefined, undefined)); } if (endSelections) { From 8503905a7cf1e66a9f6b61e7f124b89b2270ecc2 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Sep 2020 09:21:45 -0700 Subject: [PATCH 13/98] remove clear outputs api. --- .../api/browser/mainThreadNotebook.ts | 2 +- .../notebook/browser/contrib/coreActions.ts | 12 +++++-- .../browser/viewModel/notebookViewModel.ts | 8 ++--- .../common/model/notebookTextModel.ts | 35 ++++++++++--------- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index afd3c5345f2..0a0f0ed1903 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -566,7 +566,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo if (textModel) { this._notebookService.transformSpliceOutputs(textModel, splices); - textModel.spliceNotebookCellOutputs(cellHandle, splices); + textModel._spliceNotebookCellOutputs(cellHandle, splices); } } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 0d49ef4310c..01094e02ad7 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -20,7 +20,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { BaseCellRenderTemplate, CellEditState, CellFocusMode, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED, EXPAND_CELL_CONTENT_COMMAND_ID, NOTEBOOK_CELL_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellKind, CellUri, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellKind, CellUri, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -1290,7 +1290,15 @@ registerAction2(class extends NotebookCellAction { return; } - editor.viewModel.notebookDocument.clearCellOutput(context.cell.handle); + const cell = context.cell; + const index = editor.viewModel.notebookDocument.cells.indexOf(cell.model); + + if (index < 0) { + return; + } + + editor.viewModel.notebookDocument.applyEdit(editor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Output, index, outputs: [] }], true); + if (context.cell.metadata && context.cell.metadata?.runState !== NotebookCellRunState.Running) { context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { runState: NotebookCellRunState.Idle, diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 87bf0ef6e87..6a8db0f2b45 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -612,13 +612,13 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean = true, previouslyFocused: ICellViewModel[] = []) { const beforeSelections = previouslyFocused.map(e => e.handle); - this._notebook.createCell2(index, source, language, type, metadata, synchronous, pushUndoStop, beforeSelections, undefined); + this._notebook.createCell(index, source, language, type, metadata, synchronous, pushUndoStop, beforeSelections, undefined); // TODO, rely on createCell to be sync return this.viewCells[index]; } insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean = true): CellViewModel { - this._notebook.insertCell2(index, cell, synchronous, pushUndoStop); + this._notebook.insertCell(index, cell, synchronous, pushUndoStop); // TODO, rely on createCell to be sync // this will trigger it to synchronous update return this._viewCells[index]; } @@ -642,7 +642,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD } } - this._notebook.deleteCell2(index, synchronous, pushUndoStop, this.selectionHandles, endSelections); + this._notebook.deleteCell(index, synchronous, pushUndoStop, this.selectionHandles, endSelections); } /** @@ -659,7 +659,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD return false; } - this._notebook.moveCellToIdx2(index, length, newIdx, synchronous, pushedToUndoStack, undefined, [viewCell.handle]); + this._notebook.moveCellToIdx(index, length, newIdx, synchronous, pushedToUndoStack, undefined, [viewCell.handle]); return true; } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index dbf710470ef..5bbe11d4086 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -247,12 +247,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel break; case CellEditType.Output: //TODO@joh,@rebornix no event, no undo stop (?) - this.assertIndex(edit.index); + this._assertIndex(edit.index); const cell = this.cells[edit.index]; - this.spliceNotebookCellOutputs(cell.handle, [[0, cell.outputs.length, edit.outputs]]); + // TODO@rebornix, we should do diff first + this._spliceNotebookCellOutputs(cell.handle, [[0, cell.outputs.length, edit.outputs]]); break; case CellEditType.Metadata: - this.assertIndex(edit.index); + this._assertIndex(edit.index); this.deltaCellMetadata(this.cells[edit.index].handle, edit.metadata); break; } @@ -482,21 +483,14 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); } - assertIndex(index: number) { - if (index < 0 || index >= this.cells.length) { - throw new Error(`model index out of range ${index}`); - } - } - - // TODO@rebornix should this trigger content change event? - spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[]): void { + // TODO@rebornix, once adopted the new Edit API in ext host, the method should be private. + _spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[]): void { const cell = this._mapping.get(cellHandle); if (cell) { - cell.spliceNotebookCellOutputs(splices); + this._increaseVersionId(); if (!this.transientOptions.transientOutputs) { - this._increaseVersionId(); this.setDirty(true); this._onDidChangeContent.fire(NotebookCellsChangeType.Output); } @@ -511,6 +505,16 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } + private _assertIndex(index: number) { + if (index < 0 || index >= this.cells.length) { + throw new Error(`model index out of range ${index}`); + } + } + + //#region Notebook Text Model Edit API + + // TODO@rebornix should this trigger content change event? + clearCellOutput(handle: number) { const cell = this._mapping.get(handle); if (cell) { @@ -602,7 +606,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.CellsClearOutput, versionId: this._versionId }); } - //#region Notebook Text Model Edit API createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { const cell = this.createCellTextModel(source, language, type, [], metadata); @@ -663,8 +666,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }, beforeSelections, endSelections)); } - this.assertIndex(index); - this.assertIndex(newIdx); + this._assertIndex(index); + this._assertIndex(newIdx); { const cells = this.cells.splice(index, length); From 08a33550cfb4caaf2355cf110d0d89fac98a3017 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Sep 2020 09:29:43 -0700 Subject: [PATCH 14/98] remove clear all cell outputs --- .../notebook/browser/contrib/coreActions.ts | 5 +++- .../common/model/notebookTextModel.ts | 25 ------------------- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 01094e02ad7..709ab01c7df 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -1431,7 +1431,10 @@ registerAction2(class extends NotebookAction { return; } - editor.viewModel.notebookDocument.clearAllCellOutputs(); + editor.viewModel.notebookDocument.applyEdit(editor.viewModel.notebookDocument.versionId, + editor.viewModel.notebookDocument.cells.map((cell, index) => ({ + editType: CellEditType.Output, index, outputs: [] + })), true); } }); diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 5bbe11d4086..817d0a7cca5 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -513,20 +513,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel //#region Notebook Text Model Edit API - // TODO@rebornix should this trigger content change event? - - clearCellOutput(handle: number) { - const cell = this._mapping.get(handle); - if (cell) { - cell.spliceNotebookCellOutputs([ - [0, cell.outputs.length, []] - ]); - - this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.CellClearOutput, versionId: this._versionId, index: this.cells.indexOf(cell) }); - } - } - changeCellLanguage(handle: number, languageId: string) { const cell = this._mapping.get(handle); if (cell && cell.language !== languageId) { @@ -596,17 +582,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } } - clearAllCellOutputs() { - this.cells.forEach(cell => { - cell.spliceNotebookCellOutputs([ - [0, cell.outputs.length, []] - ]); - }); - this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.CellsClearOutput, versionId: this._versionId }); - } - - createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { const cell = this.createCellTextModel(source, language, type, [], metadata); From 5df865762783fbd43a4d2e4bf134d1d5748cae9d Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Sep 2020 09:35:36 -0700 Subject: [PATCH 15/98] remove notebookTextModel#createCell --- .../browser/viewModel/notebookViewModel.ts | 5 +++-- .../common/model/notebookTextModel.ts | 22 ++++--------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 6a8db0f2b45..04fcb961000 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -612,13 +612,14 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean = true, previouslyFocused: ICellViewModel[] = []) { const beforeSelections = previouslyFocused.map(e => e.handle); - this._notebook.createCell(index, source, language, type, metadata, synchronous, pushUndoStop, beforeSelections, undefined); + const cell = this._notebook.createCellTextModel(source, language, type, [], metadata); + this._notebook.insertCell(index, cell, synchronous, pushUndoStop, beforeSelections, undefined); // TODO, rely on createCell to be sync return this.viewCells[index]; } insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean = true): CellViewModel { - this._notebook.insertCell(index, cell, synchronous, pushUndoStop); + this._notebook.insertCell(index, cell, synchronous, pushUndoStop, undefined, undefined); // TODO, rely on createCell to be sync // this will trigger it to synchronous update return this._viewCells[index]; } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 817d0a7cca5..d1cea605744 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -582,9 +582,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } } - createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { - const cell = this.createCellTextModel(source, language, type, [], metadata); - + insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): void { if (pushUndoStop) { this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, @@ -593,25 +591,11 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }, beforeSelections, endSelections)); } - this._insertNewCell(index, [cell], synchronous); if (endSelections) { this._emitSelections.fire(endSelections); } - return cell; - } - - insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean): void { - if (pushUndoStop) { - this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { - insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, - deleteCell: (index) => { this._removeCell(index, 1, true); }, - emitSelections: (selections) => { this._emitSelections.fire(selections); } - }, undefined, undefined)); - } - - this._insertNewCell(index, [cell], synchronous); } deleteCell(index: number, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { @@ -683,7 +667,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel let insertIndex = index + 1; const newCells = []; for (let j = 1; j < newLinesContents.length; j++, insertIndex++) { - newCells.push(this.createCell(insertIndex, newLinesContents[j], language, kind, undefined, true, false, undefined, undefined)); + const cell = this.createCellTextModel(newLinesContents[j], language, kind, [], undefined); + this.insertCell(insertIndex, cell, true, false, undefined, undefined); + newCells.push(cell); } if (endSelections) { From faa1dd8ed4039659f6c2e0f8ef98595ca598e4db Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Sep 2020 09:43:43 -0700 Subject: [PATCH 16/98] remove deltaMetadata. --- .../contrib/notebook/browser/contrib/coreActions.ts | 13 +++++++------ .../notebook/browser/view/renderers/cellRenderer.ts | 5 +++-- .../notebook/common/model/notebookTextModel.ts | 12 +----------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 709ab01c7df..eedc6fd9cea 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -1300,12 +1300,13 @@ registerAction2(class extends NotebookCellAction { editor.viewModel.notebookDocument.applyEdit(editor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Output, index, outputs: [] }], true); if (context.cell.metadata && context.cell.metadata?.runState !== NotebookCellRunState.Running) { - context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { + context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { + ...context.cell.metadata, runState: NotebookCellRunState.Idle, runStartTime: undefined, lastRunDuration: undefined, statusMessage: undefined - }); + }, true); } } }); @@ -1573,7 +1574,7 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { inputCollapsed: true }); + context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, inputCollapsed: true }, true); } }); @@ -1596,7 +1597,7 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { inputCollapsed: false }); + context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, inputCollapsed: false }, true); } }); @@ -1619,7 +1620,7 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { outputCollapsed: true }); + context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, outputCollapsed: true }, true); } }); @@ -1642,7 +1643,7 @@ registerAction2(class extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { outputCollapsed: false }); + context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, outputCollapsed: false }, true); } }); 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 0e5f4b4bda5..71d8ba227e5 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -333,9 +333,10 @@ abstract class AbstractCellRenderer { } if (templateData.currentRenderedCell.metadata?.inputCollapsed) { - this.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(templateData.currentRenderedCell.handle, { inputCollapsed: false }); + + this.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(templateData.currentRenderedCell.handle, { ...templateData.currentRenderedCell.metadata, inputCollapsed: false }, true); } else if (templateData.currentRenderedCell.metadata?.outputCollapsed) { - this.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(templateData.currentRenderedCell.handle, { outputCollapsed: false }); + this.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(templateData.currentRenderedCell.handle, { ...templateData.currentRenderedCell.metadata, outputCollapsed: false }, true); } })); } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index d1cea605744..343add4f707 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -254,7 +254,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel break; case CellEditType.Metadata: this._assertIndex(edit.index); - this.deltaCellMetadata(this.cells[edit.index].handle, edit.metadata); + this.changeCellMetadata(this.cells[edit.index].handle, { ...this.cells[edit.index].metadata, ...edit.metadata }, true); break; } } @@ -572,16 +572,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata }); } - deltaCellMetadata(handle: number, newMetadata: NotebookCellMetadata) { - const cell = this._mapping.get(handle); - if (cell) { - this.changeCellMetadata(handle, { - ...cell.metadata, - ...newMetadata - }, true); - } - } - insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): void { if (pushUndoStop) { this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { From 313fb760fe9cce0b500eee8ebac59d3fcbab91db Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Sep 2020 10:02:30 -0700 Subject: [PATCH 17/98] make changeMetadata private --- .../api/browser/mainThreadNotebook.ts | 11 +- .../notebook/browser/contrib/coreActions.ts | 62 +++++++---- .../notebook/browser/diff/cellComponents.ts | 12 ++- .../browser/view/renderers/cellRenderer.ts | 18 +++- .../common/model/notebookTextModel.ts | 100 +++++++++--------- 5 files changed, 126 insertions(+), 77 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 0a0f0ed1903..c5b64e0eff4 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -557,7 +557,16 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo async $updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata): Promise { this.logService.debug('MainThreadNotebooks#updateNotebookCellMetadata', resource.path, handle, metadata); const textModel = this._notebookService.getNotebookTextModel(URI.from(resource)); - textModel?.changeCellMetadata(handle, metadata, true); + if (!textModel) { + return; + } + + const index = textModel.cells.findIndex(cell => cell.handle === handle); + if (index < 0) { + return; + } + + textModel.applyEdit(textModel.versionId, [{ editType: CellEditType.Metadata, index, metadata }], true); } async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[]): Promise { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index eedc6fd9cea..d7ac66ddb27 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -20,7 +20,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; import { BaseCellRenderTemplate, CellEditState, CellFocusMode, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_OUTPUT_FOCUSED, EXPAND_CELL_CONTENT_COMMAND_ID, NOTEBOOK_CELL_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellEditType, CellKind, CellUri, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellKind, CellUri, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -1300,13 +1300,15 @@ registerAction2(class extends NotebookCellAction { editor.viewModel.notebookDocument.applyEdit(editor.viewModel.notebookDocument.versionId, [{ editType: CellEditType.Output, index, outputs: [] }], true); if (context.cell.metadata && context.cell.metadata?.runState !== NotebookCellRunState.Running) { - context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { - ...context.cell.metadata, - runState: NotebookCellRunState.Idle, - runStartTime: undefined, - lastRunDuration: undefined, - statusMessage: undefined - }, true); + context.notebookEditor.viewModel!.notebookDocument.applyEdit(context.notebookEditor.viewModel!.notebookDocument.versionId, [{ + editType: CellEditType.Metadata, index, metadata: { + ...context.cell.metadata, + runState: NotebookCellRunState.Idle, + runStartTime: undefined, + lastRunDuration: undefined, + statusMessage: undefined + } + }], true); } } }); @@ -1555,7 +1557,27 @@ registerAction2(class extends NotebookCellAction { } }); -registerAction2(class extends NotebookCellAction { +abstract class ChangeNotebookCellMetadataAction extends NotebookCellAction { + async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { + const cell = context.cell; + const textModel = context.notebookEditor.viewModel?.notebookDocument; + if (!textModel) { + return; + } + + const index = textModel.cells.indexOf(cell.model); + + if (index < 0) { + return; + } + + textModel.applyEdit(textModel.versionId, [{ editType: CellEditType.Metadata, index, metadata: { ...context.cell.metadata, ...this.getMetadataDelta() } }], true); + } + + abstract getMetadataDelta(): NotebookCellMetadata; +} + +registerAction2(class extends ChangeNotebookCellMetadataAction { constructor() { super({ id: COLLAPSE_CELL_INPUT_COMMAND_ID, @@ -1573,12 +1595,12 @@ registerAction2(class extends NotebookCellAction { }); } - async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, inputCollapsed: true }, true); + getMetadataDelta(): NotebookCellMetadata { + return { inputCollapsed: true }; } }); -registerAction2(class extends NotebookCellAction { +registerAction2(class extends ChangeNotebookCellMetadataAction { constructor() { super({ id: EXPAND_CELL_CONTENT_COMMAND_ID, @@ -1596,12 +1618,12 @@ registerAction2(class extends NotebookCellAction { }); } - async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, inputCollapsed: false }, true); + getMetadataDelta(): NotebookCellMetadata { + return { inputCollapsed: false }; } }); -registerAction2(class extends NotebookCellAction { +registerAction2(class extends ChangeNotebookCellMetadataAction { constructor() { super({ id: COLLAPSE_CELL_OUTPUT_COMMAND_ID, @@ -1619,12 +1641,12 @@ registerAction2(class extends NotebookCellAction { }); } - async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, outputCollapsed: true }, true); + getMetadataDelta(): NotebookCellMetadata { + return { outputCollapsed: true }; } }); -registerAction2(class extends NotebookCellAction { +registerAction2(class extends ChangeNotebookCellMetadataAction { constructor() { super({ id: EXPAND_CELL_OUTPUT_COMMAND_ID, @@ -1642,8 +1664,8 @@ registerAction2(class extends NotebookCellAction { }); } - async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { ...context.cell.metadata, outputCollapsed: false }, true); + getMetadataDelta(): NotebookCellMetadata { + return { outputCollapsed: false }; } }); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts index 6eace8686e1..327c3ee0721 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts @@ -17,7 +17,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; -import { CellUri, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellUri, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { hash } from 'vs/base/common/hash'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; @@ -451,7 +451,15 @@ abstract class AbstractCellRenderer extends Disposable { if (newLangauge !== undefined && newLangauge !== this.cell.modified!.language) { this.notebookEditor.textModel!.changeCellLanguage(this.cell.modified!.handle, newLangauge); } - this.notebookEditor.textModel!.changeCellMetadata(this.cell.modified!.handle, result, false); + const index = this.notebookEditor.textModel!.cells.indexOf(this.cell.modified!); + + if (index < 0) { + return; + } + + this.notebookEditor.textModel!.applyEdit(this.notebookEditor.textModel!.versionId, [ + { editType: CellEditType.Metadata, index, metadata: result } + ], true); } catch { } } 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 71d8ba227e5..fcffc8ee0fd 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -48,7 +48,7 @@ import { StatefulMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellKind, NotebookCellMetadata, NotebookCellRunState, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellEditType, CellKind, NotebookCellMetadata, NotebookCellRunState, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { createAndFillInActionBarActionsWithVerticalSeparators, VerticalSeparator, VerticalSeparatorViewItem } from './cellActionView'; const $ = DOM.$; @@ -332,11 +332,21 @@ abstract class AbstractCellRenderer { return; } - if (templateData.currentRenderedCell.metadata?.inputCollapsed) { + const textModel = this.notebookEditor.viewModel!.notebookDocument; + const index = textModel.cells.indexOf(templateData.currentRenderedCell.model); - this.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(templateData.currentRenderedCell.handle, { ...templateData.currentRenderedCell.metadata, inputCollapsed: false }, true); + if (index < 0) { + return; + } + + if (templateData.currentRenderedCell.metadata?.inputCollapsed) { + textModel.applyEdit(textModel.versionId, [ + { editType: CellEditType.Metadata, index, metadata: { ...templateData.currentRenderedCell.metadata, inputCollapsed: false } } + ], true); } else if (templateData.currentRenderedCell.metadata?.outputCollapsed) { - this.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(templateData.currentRenderedCell.handle, { ...templateData.currentRenderedCell.metadata, outputCollapsed: false }, true); + textModel.applyEdit(textModel.versionId, [ + { editType: CellEditType.Metadata, index, metadata: { ...templateData.currentRenderedCell.metadata, outputCollapsed: false } } + ], true); } })); } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 343add4f707..da68e228b34 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -254,7 +254,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel break; case CellEditType.Metadata: this._assertIndex(edit.index); - this.changeCellMetadata(this.cells[edit.index].handle, { ...this.cells[edit.index].metadata, ...edit.metadata }, true); + this._changeCellMetadata(this.cells[edit.index].handle, edit.metadata, true); break; } } @@ -483,6 +483,55 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); } + private _isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata) { + const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})]); + for (let key of keys) { + if ( + (a[key as keyof NotebookCellMetadata] !== b[key as keyof NotebookCellMetadata]) + && + !(this.transientOptions.transientMetadata[key as keyof NotebookCellMetadata]) + ) { + return true; + } + } + + return false; + } + + private _changeCellMetadata(handle: number, metadata: NotebookCellMetadata, pushUndoStop: boolean) { + const cell = this.cells.find(cell => cell.handle === handle); + + if (!cell) { + return; + } + + const triggerDirtyChange = this._isCellMetadataChanged(cell.metadata, metadata); + + if (triggerDirtyChange) { + if (pushUndoStop) { + const index = this.cells.indexOf(cell); + this._operationManager.pushEditOperation(new CellMetadataEdit(this.uri, index, Object.freeze(cell.metadata), Object.freeze(metadata), { + updateCellMetadata: (index, newMetadata) => { + const cell = this.cells[index]; + if (!cell) { + return; + } + this._changeCellMetadata(cell.handle, newMetadata, false); + }, + emitSelections: (selections) => { this._emitSelections.fire(selections); } + })); + } + cell.metadata = metadata; + this.setDirty(true); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellMetadata); + } else { + cell.metadata = metadata; + } + + this._increaseVersionId(); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata }); + } + // TODO@rebornix, once adopted the new Edit API in ext host, the method should be private. _spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[]): void { const cell = this._mapping.get(cellHandle); @@ -523,55 +572,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } } - private _isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata) { - const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})]); - for (let key of keys) { - if ( - (a[key as keyof NotebookCellMetadata] !== b[key as keyof NotebookCellMetadata]) - && - !(this.transientOptions.transientMetadata[key as keyof NotebookCellMetadata]) - ) { - return true; - } - } - - return false; - } - - changeCellMetadata(handle: number, metadata: NotebookCellMetadata, pushUndoStop: boolean) { - const cell = this.cells.find(cell => cell.handle === handle); - - if (!cell) { - return; - } - - const triggerDirtyChange = this._isCellMetadataChanged(cell.metadata, metadata); - - if (triggerDirtyChange) { - if (pushUndoStop) { - const index = this.cells.indexOf(cell); - this._operationManager.pushEditOperation(new CellMetadataEdit(this.uri, index, Object.freeze(cell.metadata), Object.freeze(metadata), { - updateCellMetadata: (index, newMetadata) => { - const cell = this.cells[index]; - if (!cell) { - return; - } - this.changeCellMetadata(cell.handle, newMetadata, false); - }, - emitSelections: (selections) => { this._emitSelections.fire(selections); } - })); - } - cell.metadata = metadata; - this.setDirty(true); - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellMetadata); - } else { - cell.metadata = metadata; - } - - this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata }); - } - insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): void { if (pushUndoStop) { this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { From 1db0bcce79a1d323396611410611aab4af898253 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Sep 2020 10:24:13 -0700 Subject: [PATCH 18/98] baby step: pushEditOperations. --- .../common/model/notebookTextModel.ts | 103 ++++++++++-------- 1 file changed, 57 insertions(+), 46 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index da68e228b34..378b6aac402 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -222,14 +222,18 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._operationManager.pushStackElement(label); } + pushEditOperations(modelVersionId: number, rawEdits: ICellEditOperation[], synchronous: boolean) { + this.pushStackElement('edit'); + // every edit should push a pending element into `edit` undo stack element. + this.applyEdit(modelVersionId, rawEdits, synchronous); + this.pushStackElement('edit'); + } + applyEdit(modelVersionId: number, rawEdits: ICellEditOperation[], synchronous: boolean): boolean { if (modelVersionId !== this._versionId) { return false; } - const oldViewCells = this.cells.slice(0); - const oldMap = new Map(this._mapping); - const edits = rawEdits.map((edit, index) => { return { edit, @@ -243,7 +247,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel for (const { edit } of edits) { switch (edit.editType) { case CellEditType.Replace: - this._replaceCells(edit.index, edit.count, edit.cells); + this._replaceCells(edit.index, edit.count, edit.cells, synchronous); break; case CellEditType.Output: //TODO@joh,@rebornix no event, no undo stop (?) @@ -259,6 +263,53 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } } + return true; + } + + private _replaceCells(index: number, count: number, cellDtos: ICellDto2[], synchronous: boolean): void { + + if (count === 0 && cellDtos.length === 0) { + return; + } + + this._isUntitled = false; //TODO@rebornix fishy? + const oldViewCells = this.cells.slice(0); + const oldMap = new Map(this._mapping); + + // prepare remove + for (let i = index; i < index + count; i++) { + const cell = this.cells[i]; + this._cellListeners.get(cell.handle)?.dispose(); + this._cellListeners.delete(cell.handle); + } + + // prepare add + const cells = cellDtos.map(cellDto => { + const cellHandle = this._cellhandlePool++; + const cellUri = CellUri.generate(this.uri, cellHandle); + const cell = new NotebookCellTextModel( + cellUri, cellHandle, + cellDto.source, cellDto.language, cellDto.cellKind, cellDto.outputs || [], cellDto.metadata, this.transientOptions, + this._modelService + ); + const dirtyStateListener = cell.onDidChangeContent(() => { + this.setDirty(true); + this._increaseVersionId(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + }); + this._cellListeners.set(cell.handle, dirtyStateListener); + this._mapping.set(cell.handle, cell); + return cell; + }); + + // make change + this.cells.splice(index, count, ...cells); + // should be deferred + this.setDirty(true); + this._increaseVersionId(); + this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); + + const diffs = diff(oldViewCells, this.cells, cell => { return oldMap.has(cell.handle); }).map(diff => { @@ -293,48 +344,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }, undefined, undefined)); this._onDidChangeCells.fire({ synchronous: synchronous, splices: diffs }); - return true; - } - - private _replaceCells(index: number, count: number, cellDtos: ICellDto2[]): void { - - if (count === 0 && cellDtos.length === 0) { - return; - } - - this._isUntitled = false; //TODO@rebornix fishy? - - // prepare remove - for (let i = index; i < index + count; i++) { - const cell = this.cells[i]; - this._cellListeners.get(cell.handle)?.dispose(); - this._cellListeners.delete(cell.handle); - } - - // prepare add - const cells = cellDtos.map(cellDto => { - const cellHandle = this._cellhandlePool++; - const cellUri = CellUri.generate(this.uri, cellHandle); - const cell = new NotebookCellTextModel( - cellUri, cellHandle, - cellDto.source, cellDto.language, cellDto.cellKind, cellDto.outputs || [], cellDto.metadata, this.transientOptions, - this._modelService - ); - const dirtyStateListener = cell.onDidChangeContent(() => { - this.setDirty(true); - this._increaseVersionId(); - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - }); - this._cellListeners.set(cell.handle, dirtyStateListener); - this._mapping.set(cell.handle, cell); - return cell; - }); - - // make change - this.cells.splice(index, count, ...cells); - this.setDirty(true); - this._increaseVersionId(); - this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); } handleEdit(label: string | undefined, undo: () => void, redo: () => void): void { @@ -521,6 +530,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel emitSelections: (selections) => { this._emitSelections.fire(selections); } })); } + // should be deferred cell.metadata = metadata; this.setDirty(true); this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellMetadata); @@ -537,6 +547,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const cell = this._mapping.get(cellHandle); if (cell) { cell.spliceNotebookCellOutputs(splices); + // should be deferred this._increaseVersionId(); if (!this.transientOptions.transientOutputs) { From beab3b8767402041d5c4045bd6fc41fcfbc2c588 Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 4 Sep 2020 11:09:24 -0700 Subject: [PATCH 19/98] DelayedEmitter --- .../common/model/notebookTextModel.ts | 134 +++++++++++++----- 1 file changed, 96 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 378b6aac402..2f67ae1eca2 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -106,6 +106,49 @@ export class NotebookOperationManager { } } +class DelayedEmitter { + constructor( + private readonly _onDidChangeContentEmitter: Emitter, + private readonly _onDidChangeCells: Emitter<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>, + private readonly _onDidModelChangeProxy: Emitter, + private readonly _increaseVersion: () => void, + private readonly _textModel: NotebookTextModel + + ) { + + } + + emit(data: { + triggerDirty: { value: boolean } | undefined, + contentChange: { value: NotebookCellsChangeType | undefined } | undefined, + cellsChange: { value: { synchronous: boolean, splices: NotebookCellTextModelSplice[] } } | undefined, + modelProxyChange: { value: NotebookCellsChangedEvent } | undefined, + }) { + this._increaseVersion(); + + if (data.triggerDirty && data.triggerDirty.value) { + this._textModel.setDirty(true); + } + + if (data.contentChange) { + this._onDidChangeContentEmitter.fire(data.contentChange.value); + } + + if (data.cellsChange) { + this._onDidChangeCells.fire(data.cellsChange.value); + } + + if (data.modelProxyChange) { + this._onDidModelChangeProxy.fire( + { + ...data.modelProxyChange.value, + versionId: this._textModel.versionId + } + ); + } + } +} + export class NotebookTextModel extends Disposable implements INotebookTextModel { private _cellhandlePool: number = 0; @@ -152,6 +195,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } private _operationManager: NotebookOperationManager; + private _eventEmitter: DelayedEmitter; constructor( public handle: number, @@ -166,6 +210,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.cells = []; this._operationManager = new NotebookOperationManager(this._undoService, uri); + this._eventEmitter = new DelayedEmitter( + this._onDidChangeContent, + this._onDidChangeCells, + this._onDidModelChangeProxy, + () => { this._increaseVersionId(); }, + this + ); } get isDirty() { @@ -223,10 +274,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } pushEditOperations(modelVersionId: number, rawEdits: ICellEditOperation[], synchronous: boolean) { + // this._eventEmitter.beginDeferredEmit(); this.pushStackElement('edit'); // every edit should push a pending element into `edit` undo stack element. this.applyEdit(modelVersionId, rawEdits, synchronous); this.pushStackElement('edit'); + // this._eventEmitter.endDeferredEmit(); + } applyEdit(modelVersionId: number, rawEdits: ICellEditOperation[], synchronous: boolean): boolean { @@ -304,33 +358,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel // make change this.cells.splice(index, count, ...cells); - // should be deferred - this.setDirty(true); - this._increaseVersionId(); - this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); - - const diffs = diff(oldViewCells, this.cells, cell => { return oldMap.has(cell.handle); }).map(diff => { return [diff.start, diff.deleteCount, diff.toInsert] as [number, number, NotebookCellTextModel[]]; }); - this._onDidModelChangeProxy.fire({ - kind: NotebookCellsChangeType.ModelChange, - versionId: this._versionId, - changes: diffs.map(diff => [diff[0], diff[1], diff[2].map(cell => ({ - handle: cell.handle, - uri: cell.uri, - source: cell.textBuffer.getLinesContent(), - eol: cell.textBuffer.getEOL(), - language: cell.language, - cellKind: cell.cellKind, - outputs: cell.outputs, - metadata: cell.metadata - }))] as [number, number, IMainCellDto[]]) - }); - const undoDiff = diffs.map(diff => { const deletedCells = this.cells.slice(diff[0], diff[0] + diff[1]); @@ -343,7 +376,28 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel emitSelections: (selections) => { this._emitSelections.fire(selections); } }, undefined, undefined)); - this._onDidChangeCells.fire({ synchronous: synchronous, splices: diffs }); + // should be deferred + this._eventEmitter.emit({ + triggerDirty: { value: true }, + contentChange: { value: NotebookCellsChangeType.ModelChange }, + cellsChange: { value: { synchronous: synchronous, splices: diffs } }, + modelProxyChange: { + value: { + kind: NotebookCellsChangeType.ModelChange, + versionId: this._versionId, + changes: diffs.map(diff => [diff[0], diff[1], diff[2].map(cell => ({ + handle: cell.handle, + uri: cell.uri, + source: cell.textBuffer.getLinesContent(), + eol: cell.textBuffer.getEOL(), + language: cell.language, + cellKind: cell.cellKind, + outputs: cell.outputs, + metadata: cell.metadata + }))] as [number, number, IMainCellDto[]]) + } + } + }); } handleEdit(label: string | undefined, undo: () => void, redo: () => void): void { @@ -532,14 +586,18 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } // should be deferred cell.metadata = metadata; - this.setDirty(true); - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellMetadata); } else { cell.metadata = metadata; } - this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata }); + this._eventEmitter.emit({ + triggerDirty: { value: triggerDirtyChange }, + contentChange: { value: NotebookCellsChangeType.ChangeCellMetadata }, + cellsChange: undefined, + modelProxyChange: { + value: { kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata } + } + }); } // TODO@rebornix, once adopted the new Edit API in ext host, the method should be private. @@ -547,19 +605,19 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const cell = this._mapping.get(cellHandle); if (cell) { cell.spliceNotebookCellOutputs(splices); - // should be deferred - this._increaseVersionId(); - if (!this.transientOptions.transientOutputs) { - this.setDirty(true); - this._onDidChangeContent.fire(NotebookCellsChangeType.Output); - } - - this._onDidModelChangeProxy.fire({ - kind: NotebookCellsChangeType.Output, - versionId: this.versionId, - index: this.cells.indexOf(cell), - outputs: cell.outputs ?? [] + this._eventEmitter.emit({ + triggerDirty: { value: !this.transientOptions.transientOutputs }, + contentChange: !this.transientOptions.transientOutputs ? { value: NotebookCellsChangeType.Output } : undefined, + cellsChange: undefined, + modelProxyChange: { + value: { + kind: NotebookCellsChangeType.Output, + versionId: this.versionId, + index: this.cells.indexOf(cell), + outputs: cell.outputs ?? [] + } + } }); } From a8c46c8550309d612ec33e203ed46e283e2e76cd Mon Sep 17 00:00:00 2001 From: Mosh Feu Date: Sun, 6 Sep 2020 22:34:08 +0300 Subject: [PATCH 20/98] Add padding to space the x button --- src/vs/editor/contrib/suggest/media/suggest.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/editor/contrib/suggest/media/suggest.css b/src/vs/editor/contrib/suggest/media/suggest.css index be783ef5177..d7fb21e915b 100644 --- a/src/vs/editor/contrib/suggest/media/suggest.css +++ b/src/vs/editor/contrib/suggest/media/suggest.css @@ -351,6 +351,7 @@ box-sizing: border-box; height: 100%; width: 100%; + padding-right: 22px; } .monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .header > .type { From b985f22caaae379055651fb11031ccda5f12f7f0 Mon Sep 17 00:00:00 2001 From: Jiaxun Wei Date: Mon, 7 Sep 2020 17:26:46 +0800 Subject: [PATCH 21/98] fix #106213 --- src/vs/base/common/skipList.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vs/base/common/skipList.ts b/src/vs/base/common/skipList.ts index 1243ebdddf7..6b3bd79ef4c 100644 --- a/src/vs/base/common/skipList.ts +++ b/src/vs/base/common/skipList.ts @@ -22,7 +22,7 @@ export class SkipList implements Map { readonly [Symbol.toStringTag] = 'SkipList'; private _maxLevel: number; - private _level: number = 1; + private _level: number = 0; private _header: Node; private _size: number = 0; @@ -122,7 +122,7 @@ export class SkipList implements Map { private static _search(list: SkipList, searchKey: K, comparator: Comparator) { let x = list._header; - for (let i = list._level; i >= 0; i--) { + for (let i = list._level - 1; i >= 0; i--) { while (x.forward[i] && comparator(x.forward[i].key, searchKey) < 0) { x = x.forward[i]; } @@ -137,7 +137,7 @@ export class SkipList implements Map { private static _insert(list: SkipList, searchKey: K, value: V, comparator: Comparator) { let update: Node[] = []; let x = list._header; - for (let i = list._level; i >= 0; i--) { + for (let i = list._level - 1; i >= 0; i--) { while (x.forward[i] && comparator(x.forward[i].key, searchKey) < 0) { x = x.forward[i]; } @@ -152,13 +152,13 @@ export class SkipList implements Map { // insert let lvl = SkipList._randomLevel(list); if (lvl > list._level) { - for (let i = list._level + 1; i <= lvl; i++) { + for (let i = list._level; i < lvl; i++) { update[i] = list._header; } list._level = lvl; } x = new Node(lvl, searchKey, value); - for (let i = 0; i <= lvl; i++) { + for (let i = 0; i < lvl; i++) { x.forward[i] = update[i].forward[i]; update[i].forward[i] = x; } @@ -177,7 +177,7 @@ export class SkipList implements Map { private static _delete(list: SkipList, searchKey: K, comparator: Comparator) { let update: Node[] = []; let x = list._header; - for (let i = list._level; i >= 0; i--) { + for (let i = list._level - 1; i >= 0; i--) { while (x.forward[i] && comparator(x.forward[i].key, searchKey) < 0) { x = x.forward[i]; } @@ -194,7 +194,7 @@ export class SkipList implements Map { } update[i].forward[i] = x.forward[i]; } - while (list._level >= 1 && list._header.forward[list._level] === NIL) { + while (list._level > 0 && list._header.forward[list._level - 1] === NIL) { list._level -= 1; } return true; From 183d11a642b121c3023d3f1c9f2470263c1452bc Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Sep 2020 12:09:59 +0200 Subject: [PATCH 22/98] editors - allow to save virtual documents (fix #101952) --- .../common/editor/textResourceEditorInput.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/common/editor/textResourceEditorInput.ts b/src/vs/workbench/common/editor/textResourceEditorInput.ts index 92bb60db4ad..40a50a7c44b 100644 --- a/src/vs/workbench/common/editor/textResourceEditorInput.ts +++ b/src/vs/workbench/common/editor/textResourceEditorInput.ts @@ -137,7 +137,10 @@ export abstract class AbstractTextResourceEditorInput extends EditorInput { } isUntitled(): boolean { - return this.resource.scheme === Schemas.untitled; + // anyFile: is never untitled as it can be saved + // untitled: is untitled by definition + // anyOther: is untitled because it cannot be saved, as such we expect a "Save As" dialog + return !this.fileService.canHandleResource(this.resource); } isReadonly(): boolean { @@ -161,6 +164,14 @@ export abstract class AbstractTextResourceEditorInput extends EditorInput { } save(group: GroupIdentifier, options?: ITextFileSaveOptions): Promise { + + // If this is neither an `untitled` resource, nor a resource + // we can handle with the file service, we can only "Save As..." + if (this.resource.scheme !== Schemas.untitled && !this.fileService.canHandleResource(this.resource)) { + return this.saveAs(group, options); + } + + // Normal save return this.doSave(group, options, false); } From 007fffe1e0bfa142c11fba94dbf4ee7b88292081 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Sep 2020 12:24:15 +0200 Subject: [PATCH 23/98] editors - expose "Close Editor Group" in command palette --- src/vs/workbench/browser/parts/editor/editor.contribution.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 1f168f323af..a03f87b0bd5 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import * as nls from 'vs/nls'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor'; -import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext, EditorStickyContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor'; +import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext, EditorStickyContext, ActiveEditorAvailableEditorIdsContext, MultipleEditorGroupsContext } from 'vs/workbench/common/editor'; import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -602,6 +602,7 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorComman MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: { value: nls.localize('closeSavedEditors', "Close Saved Editors in Group"), original: 'Close Saved Editors in Group' }, category: viewCategory } }); MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: { value: nls.localize('closeOtherEditors', "Close Other Editors in Group"), original: 'Close Other Editors in Group' }, category: viewCategory } }); MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, title: { value: nls.localize('closeRightEditors', "Close Editors to the Right in Group"), original: 'Close Editors to the Right in Group' }, category: viewCategory } }); +MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITORS_AND_GROUP_COMMAND_ID, title: { value: nls.localize('closeEditorGroup', "Close Editor Group"), original: 'Close Editor Group' }, category: viewCategory }, when: MultipleEditorGroupsContext }); // File menu MenuRegistry.appendMenuItem(MenuId.MenubarRecentMenu, { From 7b239ddf8a4087488dcdf16c480a3924d34a7454 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Sep 2020 12:25:55 +0200 Subject: [PATCH 24/98] strict INotebookTextModel#cells and some more readonly-ness, https://github.com/microsoft/vscode/issues/105735 --- .../common/model/notebookTextModel.ts | 75 ++++++++++--------- .../contrib/notebook/common/notebookCommon.ts | 6 +- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index e30e36efe6f..fbbd406c807 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { Emitter, Event } from 'vs/base/common/event'; -import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellTextModelSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, NotebookCellsChangedEvent, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, IMainCellDto, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -121,7 +121,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel onDidChangeMetadata: Event = this._onDidChangeMetadata.event; private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); - cells: NotebookCellTextModel[]; + private _cells: NotebookCellTextModel[]; + + get cells(): readonly NotebookCellTextModel[] { + return this._cells; + } + private _languages: string[] = []; private _allLanguages: boolean = false; @@ -172,7 +177,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel @IModeService private readonly _modeService: IModeService, ) { super(); - this.cells = []; + this._cells = []; this._operationManager = new NotebookOperationManager(this._undoService, uri); } @@ -201,7 +206,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } initialize(cells: ICellDto2[]) { - this.cells = []; + this._cells = []; this._versionId = 0; const mainCells = cells.map(cell => { @@ -223,7 +228,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._cellListeners.set(mainCells[i].handle, dirtyStateListener); } - this.cells.splice(0, 0, ...mainCells); + this._cells.splice(0, 0, ...mainCells); this._increaseVersionId(); } @@ -236,7 +241,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return false; } - const oldViewCells = this.cells.slice(0); + const oldViewCells = this._cells.slice(0); const oldMap = new Map(this._mapping); const edits = rawEdits.map((edit, index) => { @@ -257,17 +262,17 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel case CellEditType.Output: //TODO@joh,@rebornix no event, no undo stop (?) this.assertIndex(edit.index); - const cell = this.cells[edit.index]; + const cell = this._cells[edit.index]; this.spliceNotebookCellOutputs(cell.handle, [[0, cell.outputs.length, edit.outputs]]); break; case CellEditType.Metadata: this.assertIndex(edit.index); - this.deltaCellMetadata(this.cells[edit.index].handle, edit.metadata); + this.deltaCellMetadata(this._cells[edit.index].handle, edit.metadata); break; } } - const diffs = diff(oldViewCells, this.cells, cell => { + const diffs = diff(oldViewCells, this._cells, cell => { return oldMap.has(cell.handle); }).map(diff => { return [diff.start, diff.deleteCount, diff.toInsert] as [number, number, NotebookCellTextModel[]]; @@ -289,7 +294,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }); const undoDiff = diffs.map(diff => { - const deletedCells = this.cells.slice(diff[0], diff[0] + diff[1]); + const deletedCells = this._cells.slice(diff[0], diff[0] + diff[1]); return [diff[0], deletedCells, diff[2]] as [number, NotebookCellTextModel[], NotebookCellTextModel[]]; }); @@ -314,7 +319,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel // prepare remove for (let i = index; i < index + count; i++) { - const cell = this.cells[i]; + const cell = this._cells[i]; this._cellListeners.get(cell.handle)?.dispose(); this._cellListeners.delete(cell.handle); } @@ -339,7 +344,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }); // make change - this.cells.splice(index, count, ...cells); + this._cells.splice(index, count, ...cells); this.setDirty(true); this._increaseVersionId(); this._onDidChangeContent.fire(); @@ -378,8 +383,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._languages = languages; const resolvedLanguages = this.resolvedLanguages; - if (this._isUntitled && resolvedLanguages.length && this.cells.length) { - this.cells[0].language = resolvedLanguages[0]; + if (this._isUntitled && resolvedLanguages.length && this._cells.length) { + this._cells[0].language = resolvedLanguages[0]; } } @@ -389,12 +394,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } insertTemplateCell(cell: NotebookCellTextModel) { - if (this.cells.length > 0 || this._isUntitled !== undefined) { + if (this._cells.length > 0 || this._isUntitled !== undefined) { return; } this._isUntitled = true; - this.cells = [cell]; + this._cells = [cell]; this._mapping.set(cell.handle, cell); const dirtyStateListener = cell.onDidChangeContent(() => { @@ -444,7 +449,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._cellListeners.set(cells[i].handle, dirtyStateListener); } - this.cells.splice(index, 0, ...cells); + this._cells.splice(index, 0, ...cells); this.setDirty(true); this._onDidChangeContent.fire(); @@ -478,11 +483,11 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._isUntitled = false; for (let i = index; i < index + count; i++) { - const cell = this.cells[i]; + const cell = this._cells[i]; this._cellListeners.get(cell.handle)?.dispose(); this._cellListeners.delete(cell.handle); } - this.cells.splice(index, count); + this._cells.splice(index, count); this.setDirty(true); this._onDidChangeContent.fire(); @@ -496,8 +501,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.assertIndex(index); this.assertIndex(newIdx); - const cells = this.cells.splice(index, length); - this.cells.splice(newIdx, 0, ...cells); + const cells = this._cells.splice(index, length); + this._cells.splice(newIdx, 0, ...cells); this.setDirty(true); this._onDidChangeContent.fire(); @@ -509,7 +514,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } assertIndex(index: number) { - if (index < 0 || index >= this.cells.length) { + if (index < 0 || index >= this._cells.length) { throw new Error(`model index out of range ${index}`); } } @@ -530,7 +535,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Output, versionId: this.versionId, - index: this.cells.indexOf(cell), + index: this._cells.indexOf(cell), outputs: cell.outputs ?? [] }); } @@ -545,7 +550,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel ]); this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.CellClearOutput, versionId: this._versionId, index: this.cells.indexOf(cell) }); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.CellClearOutput, versionId: this._versionId, index: this._cells.indexOf(cell) }); } } @@ -555,7 +560,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel cell.language = languageId; this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this.cells.indexOf(cell), language: languageId }); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this._cells.indexOf(cell), language: languageId }); } } @@ -575,7 +580,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } changeCellMetadata(handle: number, metadata: NotebookCellMetadata, pushUndoStop: boolean) { - const cell = this.cells.find(cell => cell.handle === handle); + const cell = this._cells.find(cell => cell.handle === handle); if (!cell) { return; @@ -585,10 +590,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel if (triggerDirtyChange) { if (pushUndoStop) { - const index = this.cells.indexOf(cell); + const index = this._cells.indexOf(cell); this._operationManager.pushEditOperation(new CellMetadataEdit(this.uri, index, Object.freeze(cell.metadata), Object.freeze(metadata), { updateCellMetadata: (index, newMetadata) => { - const cell = this.cells[index]; + const cell = this._cells[index]; if (!cell) { return; } @@ -605,7 +610,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata }); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeMetadata, versionId: this._versionId, index: this._cells.indexOf(cell), metadata: cell.metadata }); } deltaCellMetadata(handle: number, newMetadata: NotebookCellMetadata) { @@ -619,7 +624,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } clearAllCellOutputs() { - this.cells.forEach(cell => { + this._cells.forEach(cell => { cell.spliceNotebookCellOutputs([ [0, cell.outputs.length, []] ]); @@ -680,7 +685,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } deleteCell2(index: number, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { - const cell = this.cells[index]; + const cell = this._cells[index]; if (pushUndoStop) { this._operationManager.pushEditOperation(new DeleteCellEdit(this.uri, index, cell, { insertCell: this._insertCellDelegate.bind(this), @@ -697,7 +702,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } moveCellToIdx2(index: number, length: number, newIdx: number, synchronous: boolean, pushedToUndoStack: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): boolean { - const cells = this.cells.slice(index, index + length); + const cells = this._cells.slice(index, index + length); if (pushedToUndoStack) { this._operationManager.pushEditOperation(new MoveCellEdit(this.uri, index, length, newIdx, { moveCell: (fromIndex: number, length: number, toIndex: number, beforeSelections: number[] | undefined, endSelections: number[] | undefined) => { @@ -720,7 +725,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } async splitNotebookCell(index: number, newLinesContents: string[], endSelections: number[]) { - const cell = this.cells[index]; + const cell = this._cells[index]; const ref = await cell.resolveTextModelRef(); const textModel = ref.object.textEditorModel; @@ -748,8 +753,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel dispose() { this._onWillDispose.fire(); - this._cellListeners.forEach(val => val.dispose()); - this.cells.forEach(cell => cell.dispose()); + dispose(this._cellListeners.values()); + dispose(this._cells); super.dispose(); } } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index fe94a91d7ce..7a9ffe3d680 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -270,13 +270,13 @@ export interface IMetadata { } export interface INotebookTextModel { - viewType: string; + readonly viewType: string; metadata: NotebookDocumentMetadata readonly uri: URI; readonly versionId: number; languages: string[]; - cells: ICell[]; - onDidChangeCells?: Event<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>; + readonly cells: readonly ICell[]; + onDidChangeCells: Event<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>; onDidChangeContent: Event; onWillDispose(listener: () => void): IDisposable; } From 3b7fd575de671b942df4af6f10b5cbdcd6ad2d3e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Sep 2020 14:18:44 +0200 Subject: [PATCH 25/98] :lipstick: dom --- src/vs/base/browser/dom.ts | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 9349efc2792..fe50083857a 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -12,7 +12,6 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; -import { coalesce } from 'vs/base/common/arrays'; import { URI } from 'vs/base/common/uri'; import { Schemas, RemoteAuthorities } from 'vs/base/common/network'; import { BrowserFeatures } from 'vs/base/browser/canIUse'; @@ -1012,20 +1011,23 @@ export function prepend(parent: HTMLElement, child: T): T { return child; } -const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/; -export function reset(parent: HTMLElement, ...children: Array) { +/** + * Removes all children from `parent` and appends `children` + */ +export function reset(parent: HTMLElement, ...children: Array) { parent.innerText = ''; - coalesce(children) - .forEach(child => { - if (child instanceof Node) { - parent.appendChild(child); - } else { - parent.appendChild(document.createTextNode(child as string)); - } - }); + for (const child of children) { + if (child instanceof Node) { + parent.appendChild(child); + } else if (typeof child === 'string') { + parent.appendChild(document.createTextNode(child)); + } + } } +const SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((\.([\w\-]+))*)/; + export enum Namespace { HTML = 'http://www.w3.org/1999/xhtml', SVG = 'http://www.w3.org/2000/svg' @@ -1075,14 +1077,13 @@ function _$(namespace: Namespace, description: string, attrs? } }); - coalesce(children) - .forEach(child => { - if (child instanceof Node) { - result.appendChild(child); - } else { - result.appendChild(document.createTextNode(child as string)); - } - }); + for (const child of children) { + if (child instanceof Node) { + result.appendChild(child); + } else if (typeof child === 'string') { + result.appendChild(document.createTextNode(child)); + } + } return result as T; } From 6b45e457ebde51e9ed870f63e7f9e9f12b5de4e5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Sep 2020 14:37:57 +0200 Subject: [PATCH 26/98] Trusted Types - no innerHTML usage in HighlightedLabel --- .../ui/highlightedlabel/highlightedLabel.ts | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts index e408f21afd2..f5599033976 100644 --- a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts +++ b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as objects from 'vs/base/common/objects'; -import { renderCodicons } from 'vs/base/common/codicons'; -import { escape } from 'vs/base/common/strings'; +import * as dom from 'vs/base/browser/dom'; +import { renderCodiconsAsElement } from 'vs/base/browser/codicons'; export interface IHighlight { start: number; @@ -15,7 +15,7 @@ export interface IHighlight { export class HighlightedLabel { - private domNode: HTMLElement; + private readonly domNode: HTMLElement; private text: string = ''; private title: string = ''; private highlights: IHighlight[] = []; @@ -44,10 +44,6 @@ export class HighlightedLabel { return; } - if (!Array.isArray(highlights)) { - highlights = []; - } - this.text = text; this.title = title; this.highlights = highlights; @@ -56,7 +52,7 @@ export class HighlightedLabel { private render(): void { - let htmlContent = ''; + const children: HTMLSpanElement[] = []; let pos = 0; for (const highlight of this.highlights) { @@ -64,31 +60,26 @@ export class HighlightedLabel { continue; } if (pos < highlight.start) { - htmlContent += ''; const substring = this.text.substring(pos, highlight.start); - htmlContent += this.supportCodicons ? renderCodicons(escape(substring)) : escape(substring); - htmlContent += ''; + children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodiconsAsElement(substring) : [substring])); pos = highlight.end; } - if (highlight.extraClasses) { - htmlContent += ``; - } else { - htmlContent += ``; - } + const substring = this.text.substring(highlight.start, highlight.end); - htmlContent += this.supportCodicons ? renderCodicons(escape(substring)) : escape(substring); - htmlContent += ''; + const element = dom.$('span.highlight', undefined, ...this.supportCodicons ? renderCodiconsAsElement(substring) : [substring]); + if (highlight.extraClasses) { + element.classList.add(highlight.extraClasses); + } + children.push(element); pos = highlight.end; } if (pos < this.text.length) { - htmlContent += ''; - const substring = this.text.substring(pos); - htmlContent += this.supportCodicons ? renderCodicons(escape(substring)) : escape(substring); - htmlContent += ''; + const substring = this.text.substring(pos,); + children.push(dom.$('span', undefined, ...this.supportCodicons ? renderCodiconsAsElement(substring) : [substring])); } - this.domNode.innerHTML = htmlContent; + dom.reset(this.domNode, ...children); if (this.title) { this.domNode.title = this.title; } else { From 79c4f10983149bf4420fa20597dfe26f05c85506 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 7 Sep 2020 15:24:57 +0200 Subject: [PATCH 27/98] Fix #106021 --- src/vs/code/electron-main/main.ts | 2 +- .../backup/electron-main/backupMainService.ts | 2 +- .../environment/common/environment.ts | 4 +- .../environment/node/environmentService.ts | 6 +- .../electron-main/windowsMainService.ts | 2 +- .../electron-browser/desktop.main.ts | 6 +- .../electron-sandbox/desktop.main.ts | 2 +- .../sandbox.simpleservices.ts | 3 +- .../backup/common/backupFileService.ts | 4 +- .../backup/electron-sandbox/backup.ts | 12 - .../backupFileService.test.ts | 8 +- .../configurationEditingService.test.ts | 2 +- .../configurationService.test.ts | 14 +- .../environment/browser/environmentService.ts | 22 +- .../environment/common/environmentService.ts | 7 +- .../electron-browser/environmentService.ts | 6 +- .../electron-sandbox/environmentService.ts | 6 +- .../keybindingEditing.test.ts | 2 +- .../userData/common/fileUserDataProvider.ts | 18 +- .../fileUserDataProvider.test.ts | 226 ++++++++---------- .../workspaceEditingService.ts | 2 - 21 files changed, 160 insertions(+), 196 deletions(-) delete mode 100644 src/vs/workbench/services/backup/electron-sandbox/backup.ts diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 66f1cd08c3e..d0ae1450567 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -184,7 +184,7 @@ class CodeMain { environmentService.logsPath, environmentService.globalStorageHome.fsPath, environmentService.workspaceStorageHome.fsPath, - environmentService.backupHome.fsPath + environmentService.backupHome ].map((path): undefined | Promise => path ? mkdirp(path) : undefined)); // Configuration service diff --git a/src/vs/platform/backup/electron-main/backupMainService.ts b/src/vs/platform/backup/electron-main/backupMainService.ts index b323b460034..98467412ab0 100644 --- a/src/vs/platform/backup/electron-main/backupMainService.ts +++ b/src/vs/platform/backup/electron-main/backupMainService.ts @@ -42,7 +42,7 @@ export class BackupMainService implements IBackupMainService { @IConfigurationService private readonly configurationService: IConfigurationService, @ILogService private readonly logService: ILogService ) { - this.backupHome = environmentService.backupHome.fsPath; + this.backupHome = environmentService.backupHome; this.workspacesJsonPath = environmentService.backupWorkspacesPath; } diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index acd11a3d65d..8ce5820075f 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -18,8 +18,6 @@ export interface IExtensionHostDebugParams extends IDebugParams { debugId?: string; } -export const BACKUPS = 'Backups'; - /** * A basic environment service that can be used in various processes, * such as main, renderer and shared process. Use subclasses of this @@ -44,7 +42,6 @@ export interface IEnvironmentService { snippetsHome: URI; // --- data paths - backupHome: URI; untitledWorkspacesHome: URI; globalStorageHome: URI; @@ -100,6 +97,7 @@ export interface INativeEnvironmentService extends IEnvironmentService { appSettingsHome: URI; userDataPath: string; machineSettingsResource: URI; + backupHome: string; backupWorkspacesPath: string; nodeCachedDataDir?: string; installSourcePath: string; diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index ef8dc5d2dd5..01459254fa0 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IDebugParams, IExtensionHostDebugParams, BACKUPS, INativeEnvironmentService } from 'vs/platform/environment/common/environment'; +import { IDebugParams, IExtensionHostDebugParams, INativeEnvironmentService } from 'vs/platform/environment/common/environment'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import * as crypto from 'crypto'; import * as paths from 'vs/base/node/paths'; @@ -94,10 +94,10 @@ export class EnvironmentService implements INativeEnvironmentService { get isExtensionDevelopment(): boolean { return !!this._args.extensionDevelopmentPath; } @memoize - get backupHome(): URI { return URI.file(path.join(this.userDataPath, BACKUPS)); } + get backupHome(): string { return path.join(this.userDataPath, 'Backups'); } @memoize - get backupWorkspacesPath(): string { return path.join(this.backupHome.fsPath, 'workspaces.json'); } + get backupWorkspacesPath(): string { return path.join(this.backupHome, 'workspaces.json'); } @memoize get untitledWorkspacesHome(): URI { return URI.file(path.join(this.userDataPath, 'Workspaces')); } diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 27381c0df22..10ecfbd55fa 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -1358,7 +1358,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // For all other cases we first call into registerEmptyWindowBackupSync() to set it before // loading the window. if (options.emptyWindowBackupInfo) { - configuration.backupPath = join(this.environmentService.backupHome.fsPath, options.emptyWindowBackupInfo.backupFolder); + configuration.backupPath = join(this.environmentService.backupHome, options.emptyWindowBackupInfo.backupFolder); } let window: ICodeWindow | undefined; diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index 47e1fdcf5d5..52d61bf7087 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -206,7 +206,7 @@ class DesktopMain extends Disposable { fileService.registerProvider(Schemas.file, diskFileSystemProvider); // User Data Provider - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(this.environmentService.appSettingsHome, this.environmentService.backupHome, diskFileSystemProvider, this.environmentService, logService)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(this.environmentService.appSettingsHome, this.environmentService.configuration.backupPath ? URI.file(this.environmentService.configuration.backupPath) : undefined, diskFileSystemProvider, this.environmentService, logService)); const connection = remoteAgentService.getConnection(); if (connection) { @@ -259,8 +259,8 @@ class DesktopMain extends Disposable { // Fallback to empty workspace if we have no payload yet. if (!workspaceInitializationPayload) { let id: string; - if (this.environmentService.configuration.backupWorkspaceResource) { - id = basename(this.environmentService.configuration.backupWorkspaceResource); // we know the backupPath must be a unique path so we leverage its name as workspace ID + if (this.environmentService.backupWorkspaceHome) { + id = basename(this.environmentService.backupWorkspaceHome); // we know the backupPath must be a unique path so we leverage its name as workspace ID } else if (this.environmentService.isExtensionDevelopment) { id = 'ext-dev'; // extension development window never stores backups and is a singleton } else { diff --git a/src/vs/workbench/electron-sandbox/desktop.main.ts b/src/vs/workbench/electron-sandbox/desktop.main.ts index 11a57edd768..9d53f97e8fb 100644 --- a/src/vs/workbench/electron-sandbox/desktop.main.ts +++ b/src/vs/workbench/electron-sandbox/desktop.main.ts @@ -181,7 +181,7 @@ class DesktopMain extends Disposable { fileService.registerProvider(Schemas.file, simpleFileSystemProvider); // User Data Provider - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(URI.file('user-home'), this.environmentService.backupHome, simpleFileSystemProvider, this.environmentService, logService)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(URI.file('user-home'), undefined, simpleFileSystemProvider, this.environmentService, logService)); const connection = remoteAgentService.getConnection(); if (connection) { diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index 8dbebb9eef7..1159fe856e7 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -91,7 +91,7 @@ export class SimpleWorkbenchEnvironmentService implements INativeWorkbenchEnviro get serviceMachineIdResource(): URI { return joinPath(this.userRoamingDataHome, 'machineid'); } get userDataSyncLogResource(): URI { return joinPath(this.userRoamingDataHome, 'syncLog'); } get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'syncHome'); } - get backupHome(): URI { return joinPath(this.userRoamingDataHome, 'backupsHome'); } + get backupWorkspaceHome(): URI { return joinPath(this.userRoamingDataHome, 'Backups', 'workspace'); } options?: IWorkbenchConstructionOptions | undefined; logExtensionHostCommunication?: boolean | undefined; @@ -120,6 +120,7 @@ export class SimpleWorkbenchEnvironmentService implements INativeWorkbenchEnviro appSettingsHome: URI = undefined!; userDataPath: string = undefined!; machineSettingsResource: URI = undefined!; + backupHome: string = undefined!; backupWorkspacesPath: string = undefined!; log?: string | undefined; diff --git a/src/vs/workbench/services/backup/common/backupFileService.ts b/src/vs/workbench/services/backup/common/backupFileService.ts index 71fcefaae3a..175d5e9ecca 100644 --- a/src/vs/workbench/services/backup/common/backupFileService.ts +++ b/src/vs/workbench/services/backup/common/backupFileService.ts @@ -128,7 +128,7 @@ export class BackupFileService implements IBackupFileService { } private initialize(): BackupFileServiceImpl | InMemoryBackupFileService { - const backupWorkspaceResource = this.environmentService.configuration.backupWorkspaceResource; + const backupWorkspaceResource = this.environmentService.backupWorkspaceHome; if (backupWorkspaceResource) { return new BackupFileServiceImpl(backupWorkspaceResource, this.hashPath, this.fileService, this.logService); } @@ -140,7 +140,7 @@ export class BackupFileService implements IBackupFileService { // Re-init implementation (unless we are running in-memory) if (this.impl instanceof BackupFileServiceImpl) { - const backupWorkspaceResource = this.environmentService.configuration.backupWorkspaceResource; + const backupWorkspaceResource = this.environmentService.backupWorkspaceHome; if (backupWorkspaceResource) { this.impl.initialize(backupWorkspaceResource); } else { diff --git a/src/vs/workbench/services/backup/electron-sandbox/backup.ts b/src/vs/workbench/services/backup/electron-sandbox/backup.ts deleted file mode 100644 index 4e1c308b73b..00000000000 --- a/src/vs/workbench/services/backup/electron-sandbox/backup.ts +++ /dev/null @@ -1,12 +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 } from 'vs/base/common/uri'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; -import { joinPath, relativePath } from 'vs/base/common/resources'; - -export function toBackupWorkspaceResource(backupWorkspacePath: string, environmentService: INativeWorkbenchEnvironmentService): URI { - return joinPath(environmentService.userRoamingDataHome, relativePath(URI.file(environmentService.userDataPath), URI.file(backupWorkspacePath))!); -} diff --git a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts index 94dfd77136f..4da557d1732 100644 --- a/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts +++ b/src/vs/workbench/services/backup/test/electron-browser/backupFileService.test.ts @@ -24,13 +24,11 @@ import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environ import { snapshotToString } from 'vs/workbench/services/textfile/common/textfiles'; import { IFileService } from 'vs/platform/files/common/files'; import { hashPath, BackupFileService } from 'vs/workbench/services/backup/node/backupFileService'; -import { BACKUPS } from 'vs/platform/environment/common/environment'; import { FileUserDataProvider } from 'vs/workbench/services/userData/common/fileUserDataProvider'; import { VSBuffer } from 'vs/base/common/buffer'; import { TestWorkbenchConfiguration } from 'vs/workbench/test/electron-browser/workbenchTestServices'; const userdataDir = getRandomTestPath(os.tmpdir(), 'vsctests', 'backupfileservice'); -const appSettingsHome = path.join(userdataDir, 'User'); const backupHome = path.join(userdataDir, 'Backups'); const workspacesJsonPath = path.join(backupHome, 'workspaces.json'); @@ -67,7 +65,7 @@ export class NodeTestBackupFileService extends BackupFileService { const fileService = new FileService(logService); const diskFileSystemProvider = new DiskFileSystemProvider(logService); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, logService)); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, URI.file(workspaceBackupPath), diskFileSystemProvider, environmentService, logService)); super(environmentService, fileService, logService); @@ -159,7 +157,7 @@ suite('BackupFileService', () => { const backupResource = fooFile; const workspaceHash = hashPath(workspaceResource); const filePathHash = hashPath(backupResource); - const expectedPath = URI.file(path.join(appSettingsHome, BACKUPS, workspaceHash, Schemas.file, filePathHash)).with({ scheme: Schemas.userData }).toString(); + const expectedPath = URI.file(path.join(backupHome, workspaceHash, Schemas.file, filePathHash)).with({ scheme: Schemas.userData }).toString(); assert.equal(service.toBackupResource(backupResource).toString(), expectedPath); }); @@ -168,7 +166,7 @@ suite('BackupFileService', () => { const backupResource = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' }); const workspaceHash = hashPath(workspaceResource); const filePathHash = hashPath(backupResource); - const expectedPath = URI.file(path.join(appSettingsHome, BACKUPS, workspaceHash, Schemas.untitled, filePathHash)).with({ scheme: Schemas.userData }).toString(); + const expectedPath = URI.file(path.join(backupHome, workspaceHash, Schemas.untitled, filePathHash)).with({ scheme: Schemas.userData }).toString(); assert.equal(service.toBackupResource(backupResource).toString(), expectedPath); }); }); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts index 0e651c0bee7..40e66c9b1f4 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationEditingService.test.ts @@ -110,7 +110,7 @@ suite('ConfigurationEditingService', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); instantiationService.stub(IFileService, fileService); instantiationService.stub(IRemoteAgentService, remoteAgentService); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index 290cd1de055..e04efb9e339 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -113,7 +113,7 @@ suite('WorkspaceContextService - Folder', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, new DiskFileSystemProvider(new NullLogService()), environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, new DiskFileSystemProvider(new NullLogService()), environmentService, new NullLogService())); workspaceContextService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, new RemoteAgentService(environmentService, { _serviceBrand: undefined, ...product }, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService())); return (workspaceContextService).initialize(convertToWorkspacePayload(URI.file(folderDir))); }); @@ -179,7 +179,7 @@ suite('WorkspaceContextService - Workspace', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); @@ -239,7 +239,7 @@ suite('WorkspaceContextService - Workspace Editing', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); @@ -500,7 +500,7 @@ suite('WorkspaceService - Initialization', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); @@ -777,7 +777,7 @@ suite('WorkspaceConfigurationService - Folder', () => { fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); workspaceService = disposableStore.add(new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService)); instantiationService.stub(IWorkspaceContextService, workspaceService); instantiationService.stub(IConfigurationService, workspaceService); @@ -1286,7 +1286,7 @@ suite('WorkspaceConfigurationService-Multiroot', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, workspaceService); @@ -1888,7 +1888,7 @@ suite('WorkspaceConfigurationService - Remote Folder', () => { const remoteAgentService = instantiationService.stub(IRemoteAgentService, >{ getEnvironment: () => remoteEnvironmentPromise }); const fileService = new FileService(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); const configurationCache: IConfigurationCache = { read: () => Promise.resolve(''), write: () => Promise.resolve(), remove: () => Promise.resolve() }; testObject = new WorkspaceService({ configurationCache, remoteAuthority }, environmentService, fileService, remoteAgentService); instantiationService.stub(IWorkspaceContextService, testObject); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 51d4e2d2384..17df4966d73 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -7,21 +7,20 @@ import { Schemas } from 'vs/base/common/network'; import { joinPath } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; -import { BACKUPS, IExtensionHostDebugParams } from 'vs/platform/environment/common/environment'; -import { ColorScheme, IPath } from 'vs/platform/windows/common/windows'; -import { IWorkbenchEnvironmentService, IWorkbenchConfiguration } from 'vs/workbench/services/environment/common/environmentService'; +import { IExtensionHostDebugParams } from 'vs/platform/environment/common/environment'; +import { ColorScheme, IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkbenchConstructionOptions as IWorkbenchOptions } from 'vs/workbench/workbench.web.api'; import product from 'vs/platform/product/common/product'; import { memoize } from 'vs/base/common/decorators'; import { onUnexpectedError } from 'vs/base/common/errors'; import { parseLineAndColumnAware } from 'vs/base/common/extpath'; -class BrowserWorkbenchConfiguration implements IWorkbenchConfiguration { +class BrowserWorkbenchConfiguration implements IWindowConfiguration { constructor( private readonly options: IBrowserWorkbenchOptions, - private readonly payload: Map | undefined, - private readonly backupHome: URI + private readonly payload: Map | undefined ) { } @memoize @@ -30,9 +29,6 @@ class BrowserWorkbenchConfiguration implements IWorkbenchConfiguration { @memoize get remoteAuthority(): string | undefined { return this.options.remoteAuthority; } - @memoize - get backupWorkspaceResource(): URI { return joinPath(this.backupHome, this.options.workspaceId); } - @memoize get filesToOpenOrCreate(): IPath[] | undefined { if (this.payload) { @@ -101,10 +97,10 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment declare readonly _serviceBrand: undefined; - private _configuration: IWorkbenchConfiguration | undefined = undefined; - get configuration(): IWorkbenchConfiguration { + private _configuration: IWindowConfiguration | undefined = undefined; + get configuration(): IWindowConfiguration { if (!this._configuration) { - this._configuration = new BrowserWorkbenchConfiguration(this.options, this.payload, this.backupHome); + this._configuration = new BrowserWorkbenchConfiguration(this.options, this.payload); } return this._configuration; @@ -163,7 +159,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment get keyboardLayoutResource(): URI { return joinPath(this.userRoamingDataHome, 'keyboardLayout.json'); } @memoize - get backupHome(): URI { return joinPath(this.userRoamingDataHome, BACKUPS); } + get backupWorkspaceHome(): URI { return joinPath(this.userRoamingDataHome, 'Backups', this.options.workspaceId); } @memoize get untitledWorkspacesHome(): URI { return joinPath(this.userRoamingDataHome, 'Workspaces'); } diff --git a/src/vs/workbench/services/environment/common/environmentService.ts b/src/vs/workbench/services/environment/common/environmentService.ts index 159b5c5aeef..5d0d207d53e 100644 --- a/src/vs/workbench/services/environment/common/environmentService.ts +++ b/src/vs/workbench/services/environment/common/environmentService.ts @@ -11,19 +11,16 @@ import { URI } from 'vs/base/common/uri'; export const IWorkbenchEnvironmentService = createDecorator('environmentService'); -export interface IWorkbenchConfiguration extends IWindowConfiguration { - backupWorkspaceResource?: URI; -} - export interface IWorkbenchEnvironmentService extends IEnvironmentService { readonly _serviceBrand: undefined; - readonly configuration: IWorkbenchConfiguration; + readonly configuration: IWindowConfiguration; readonly options?: IWorkbenchOptions; readonly logFile: URI; + readonly backupWorkspaceHome?: URI; readonly logExtensionHostCommunication?: boolean; readonly extensionEnabledProposedApi?: string[]; diff --git a/src/vs/workbench/services/environment/electron-browser/environmentService.ts b/src/vs/workbench/services/environment/electron-browser/environmentService.ts index c48430e0f9b..31b2a7a16ac 100644 --- a/src/vs/workbench/services/environment/electron-browser/environmentService.ts +++ b/src/vs/workbench/services/environment/electron-browser/environmentService.ts @@ -8,7 +8,6 @@ import { INativeWorkbenchConfiguration, INativeWorkbenchEnvironmentService } fro import { memoize } from 'vs/base/common/decorators'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; -import { toBackupWorkspaceResource } from 'vs/workbench/services/backup/electron-sandbox/backup'; import { dirname, join } from 'vs/base/common/path'; import product from 'vs/platform/product/common/product'; import { isLinux, isWindows } from 'vs/base/common/platform'; @@ -33,6 +32,9 @@ export class NativeWorkbenchEnvironmentService extends EnvironmentService implem @memoize get userRoamingDataHome(): URI { return this.appSettingsHome.with({ scheme: Schemas.userData }); } + // Do not memoize as `backupPath` can change in configuration + get backupWorkspaceHome(): URI | undefined { return this.configuration.backupPath ? URI.file(this.configuration.backupPath).with({ scheme: this.userRoamingDataHome.scheme }) : undefined; } + @memoize get logFile(): URI { return URI.file(join(this.logsPath, `renderer${this.configuration.windowId}.log`)); } @@ -66,8 +68,6 @@ export class NativeWorkbenchEnvironmentService extends EnvironmentService implem readonly configuration: INativeWorkbenchConfiguration ) { super(configuration); - - this.configuration.backupWorkspaceResource = this.configuration.backupPath ? toBackupWorkspaceResource(this.configuration.backupPath, this) : undefined; } private doGetCLIPath(): string { diff --git a/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts b/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts index bde5abaeb38..59e0cb235a5 100644 --- a/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts +++ b/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts @@ -3,12 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IWorkbenchConfiguration, IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { INativeWindowConfiguration, IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; import { URI } from 'vs/base/common/uri'; -export interface INativeWorkbenchConfiguration extends IWorkbenchConfiguration, INativeWindowConfiguration { } +export interface INativeWorkbenchConfiguration extends IWindowConfiguration, INativeWindowConfiguration { } export interface INativeWorkbenchEnvironmentService extends IWorkbenchEnvironmentService, INativeEnvironmentService { diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts index f4e8a645899..4d10fd8fecc 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts @@ -117,7 +117,7 @@ suite('KeybindingsEditing', () => { const fileService = new FileService(new NullLogService()); const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService, new NullLogService())); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, undefined, diskFileSystemProvider, environmentService, new NullLogService())); instantiationService.stub(IFileService, fileService); instantiationService.stub(IUriIdentityService, new UriIdentityService(fileService)); instantiationService.stub(IWorkingCopyService, new TestWorkingCopyService()); diff --git a/src/vs/workbench/services/userData/common/fileUserDataProvider.ts b/src/vs/workbench/services/userData/common/fileUserDataProvider.ts index 3289ab788b6..91158913e25 100644 --- a/src/vs/workbench/services/userData/common/fileUserDataProvider.ts +++ b/src/vs/workbench/services/userData/common/fileUserDataProvider.ts @@ -7,7 +7,6 @@ import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IFileSystemProviderWithFileReadWriteCapability, IFileChange, IWatchOptions, IStat, FileOverwriteOptions, FileType, FileWriteOptions, FileDeleteOptions, FileSystemProviderCapabilities, IFileSystemProviderWithOpenReadWriteCloseCapability, FileOpenOptions, hasReadWriteCapability, hasOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadStreamCapability, FileReadStreamOptions, hasFileReadStreamCapability } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; -import { BACKUPS } from 'vs/platform/environment/common/environment'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ReadableStreamEvents } from 'vs/base/common/stream'; @@ -26,11 +25,12 @@ export class FileUserDataProvider extends Disposable implements readonly onDidChangeFile: Event = this._onDidChangeFile.event; private readonly userDataHome: URI; + private readonly backupHome: URI | undefined; private extUri: ExtUri; constructor( private readonly fileSystemUserDataHome: URI, - private readonly fileSystemBackupsHome: URI, + private readonly fileSystemBackupsHome: URI | undefined, private readonly fileSystemProvider: IFileSystemProviderWithFileReadWriteCapability | IFileSystemProviderWithOpenReadWriteCloseCapability, environmentService: IWorkbenchEnvironmentService, private readonly logService: ILogService, @@ -38,6 +38,7 @@ export class FileUserDataProvider extends Disposable implements super(); this.userDataHome = environmentService.userRoamingDataHome; + this.backupHome = environmentService.backupWorkspaceHome; this.extUri = !!(this.capabilities & FileSystemProviderCapabilities.PathCaseSensitive) ? extUri : extUriIgnorePathCase; // update extUri as capabilites might change. @@ -139,10 +140,13 @@ export class FileUserDataProvider extends Disposable implements } private toFileSystemResource(userDataResource: URI): URI { - const relativePath = this.extUri.relativePath(this.userDataHome, userDataResource)!; - if (relativePath.startsWith(BACKUPS)) { - return this.extUri.joinPath(this.extUri.dirname(this.fileSystemBackupsHome), relativePath); + // Backup Resource + if (this.backupHome && this.fileSystemBackupsHome && this.extUri.isEqualOrParent(userDataResource, this.backupHome)) { + const relativePath = this.extUri.relativePath(this.backupHome, userDataResource); + return relativePath ? this.extUri.joinPath(this.fileSystemBackupsHome, relativePath) : this.fileSystemBackupsHome; } + + const relativePath = this.extUri.relativePath(this.userDataHome, userDataResource)!; return this.extUri.joinPath(this.fileSystemUserDataHome, relativePath); } @@ -151,9 +155,9 @@ export class FileUserDataProvider extends Disposable implements const relativePath = this.extUri.relativePath(this.fileSystemUserDataHome, fileSystemResource); return relativePath ? this.extUri.joinPath(this.userDataHome, relativePath) : this.userDataHome; } - if (this.extUri.isEqualOrParent(fileSystemResource, this.fileSystemBackupsHome)) { + if (this.backupHome && this.fileSystemBackupsHome && this.extUri.isEqualOrParent(fileSystemResource, this.fileSystemBackupsHome)) { const relativePath = this.extUri.relativePath(this.fileSystemBackupsHome, fileSystemResource); - return relativePath ? this.extUri.joinPath(this.userDataHome, BACKUPS, relativePath) : this.extUri.joinPath(this.userDataHome, BACKUPS); + return relativePath ? this.extUri.joinPath(this.backupHome, relativePath) : this.backupHome; } return null; } diff --git a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts index 7f01f78c3eb..f7ed39ac45d 100644 --- a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts +++ b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts @@ -7,7 +7,6 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as uuid from 'vs/base/common/uuid'; -import * as pfs from 'vs/base/node/pfs'; import { IFileService, FileChangeType, IFileChange, IFileSystemProviderWithFileReadWriteCapability, IStat, FileType, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; @@ -17,28 +16,19 @@ import { FileUserDataProvider } from 'vs/workbench/services/userData/common/file import { joinPath, dirname } from 'vs/base/common/resources'; import { VSBuffer } from 'vs/base/common/buffer'; import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; -import { BACKUPS } from 'vs/platform/environment/common/environment'; import { DisposableStore, IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { BrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; import { Emitter, Event } from 'vs/base/common/event'; import { timeout } from 'vs/base/common/async'; - -class TestBrowserWorkbenchEnvironmentService extends BrowserWorkbenchEnvironmentService { - - testUserRoamingDataHome!: URI; - - get userRoamingDataHome(): URI { - return this.testUserRoamingDataHome; - } -} +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; suite('FileUserDataProvider', () => { let testObject: IFileService; - let rootPath: string; - let userDataPath: string; - let backupsPath: string; - let userDataResource: URI; + let rootResource: URI; + let userDataHomeOnDisk: URI; + let backupWorkspaceHomeOnDisk: URI; + let environmentService: IWorkbenchEnvironmentService; const disposables = new DisposableStore(); setup(async () => { @@ -50,237 +40,237 @@ suite('FileUserDataProvider', () => { disposables.add(diskFileSystemProvider); disposables.add(testObject.registerProvider(Schemas.file, diskFileSystemProvider)); - rootPath = path.join(os.tmpdir(), 'vsctests', uuid.generateUuid()); - userDataPath = path.join(rootPath, 'user'); - backupsPath = path.join(rootPath, BACKUPS); - userDataResource = URI.file(userDataPath).with({ scheme: Schemas.userData }); - await Promise.all([pfs.mkdirp(userDataPath), pfs.mkdirp(backupsPath)]); + const workspaceId = 'workspaceId'; + environmentService = new BrowserWorkbenchEnvironmentService({ remoteAuthority: 'remote', workspaceId, logsPath: URI.file('logFile') }); - const environmentService = new TestBrowserWorkbenchEnvironmentService({ remoteAuthority: 'remote', workspaceId: 'workspaceId', logsPath: URI.file('logFile') }); - environmentService.testUserRoamingDataHome = userDataResource; + rootResource = URI.file(path.join(os.tmpdir(), 'vsctests', uuid.generateUuid())); + userDataHomeOnDisk = joinPath(rootResource, 'user'); + const backupHome = joinPath(rootResource, 'Backups'); + backupWorkspaceHomeOnDisk = joinPath(backupHome, workspaceId); + await Promise.all([testObject.createFolder(userDataHomeOnDisk), testObject.createFolder(backupWorkspaceHomeOnDisk)]); - const userDataFileSystemProvider = new FileUserDataProvider(URI.file(userDataPath), URI.file(backupsPath), diskFileSystemProvider, environmentService, logService); + const userDataFileSystemProvider = new FileUserDataProvider(userDataHomeOnDisk, backupWorkspaceHomeOnDisk, diskFileSystemProvider, environmentService, logService); disposables.add(userDataFileSystemProvider); disposables.add(testObject.registerProvider(Schemas.userData, userDataFileSystemProvider)); }); teardown(async () => { + await testObject.del(rootResource, { recursive: true }); disposables.clear(); - await pfs.rimraf(rootPath, pfs.RimRafMode.MOVE); }); test('exists return false when file does not exist', async () => { - const exists = await testObject.exists(joinPath(userDataResource, 'settings.json')); + const exists = await testObject.exists(environmentService.settingsResource); assert.equal(exists, false); }); test('read file throws error if not exist', async () => { try { - await testObject.readFile(joinPath(userDataResource, 'settings.json')); + await testObject.readFile(environmentService.settingsResource); assert.fail('Should fail since file does not exist'); } catch (e) { } }); test('read existing file', async () => { - await pfs.writeFile(path.join(userDataPath, 'settings.json'), '{}'); - const result = await testObject.readFile(joinPath(userDataResource, 'settings.json')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString('{}')); + const result = await testObject.readFile(environmentService.settingsResource); assert.equal(result.value, '{}'); }); test('create file', async () => { - const resource = joinPath(userDataResource, 'settings.json'); + const resource = environmentService.settingsResource; const actual1 = await testObject.createFile(resource, VSBuffer.fromString('{}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual2 = await pfs.readFile(path.join(userDataPath, 'settings.json')); - assert.equal(actual2, '{}'); + const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'settings.json')); + assert.equal(actual2.value.toString(), '{}'); }); test('write file creates the file if not exist', async () => { - const resource = joinPath(userDataResource, 'settings.json'); + const resource = environmentService.settingsResource; const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual2 = await pfs.readFile(path.join(userDataPath, 'settings.json')); - assert.equal(actual2, '{}'); + const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'settings.json')); + assert.equal(actual2.value.toString(), '{}'); }); test('write to existing file', async () => { - const resource = joinPath(userDataResource, 'settings.json'); - await pfs.writeFile(path.join(userDataPath, 'settings.json'), '{}'); + const resource = environmentService.settingsResource; + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString('{}')); const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{a:1}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual2 = await pfs.readFile(path.join(userDataPath, 'settings.json')); - assert.equal(actual2, '{a:1}'); + const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'settings.json')); + assert.equal(actual2.value.toString(), '{a:1}'); }); test('delete file', async () => { - await pfs.writeFile(path.join(userDataPath, 'settings.json'), ''); - await testObject.del(joinPath(userDataResource, 'settings.json')); - const result = await pfs.exists(path.join(userDataPath, 'settings.json')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString('')); + await testObject.del(environmentService.settingsResource); + const result = await testObject.exists(joinPath(userDataHomeOnDisk, 'settings.json')); assert.equal(false, result); }); test('resolve file', async () => { - await pfs.writeFile(path.join(userDataPath, 'settings.json'), ''); - const result = await testObject.resolve(joinPath(userDataResource, 'settings.json')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'settings.json'), VSBuffer.fromString('')); + const result = await testObject.resolve(environmentService.settingsResource); assert.ok(!result.isDirectory); assert.ok(result.children === undefined); }); test('exists return false for folder that does not exist', async () => { - const exists = await testObject.exists(joinPath(userDataResource, 'snippets')); + const exists = await testObject.exists(environmentService.snippetsHome); assert.equal(exists, false); }); test('exists return true for folder that exists', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); - const exists = await testObject.exists(joinPath(userDataResource, 'snippets')); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); + const exists = await testObject.exists(environmentService.snippetsHome); assert.equal(exists, true); }); test('read file throws error for folder', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); try { - await testObject.readFile(joinPath(userDataResource, 'snippets')); + await testObject.readFile(environmentService.snippetsHome); assert.fail('Should fail since read file is not supported for folders'); } catch (e) { } }); test('read file under folder', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); - await pfs.writeFile(path.join(userDataPath, 'snippets', 'settings.json'), '{}'); - const resource = joinPath(userDataResource, 'snippets/settings.json'); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}')); + const resource = joinPath(environmentService.snippetsHome, 'settings.json'); const actual = await testObject.readFile(resource); assert.equal(actual.resource.toString(), resource.toString()); assert.equal(actual.value, '{}'); }); test('read file under sub folder', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets', 'java')); - await pfs.writeFile(path.join(userDataPath, 'snippets', 'java', 'settings.json'), '{}'); - const resource = joinPath(userDataResource, 'snippets/java/settings.json'); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets', 'java')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'java', 'settings.json'), VSBuffer.fromString('{}')); + const resource = joinPath(environmentService.snippetsHome, 'java/settings.json'); const actual = await testObject.readFile(resource); assert.equal(actual.resource.toString(), resource.toString()); assert.equal(actual.value, '{}'); }); test('create file under folder that exists', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); - const resource = joinPath(userDataResource, 'snippets/settings.json'); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); + const resource = joinPath(environmentService.snippetsHome, 'settings.json'); const actual1 = await testObject.createFile(resource, VSBuffer.fromString('{}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual2 = await pfs.readFile(path.join(userDataPath, 'snippets', 'settings.json')); - assert.equal(actual2, '{}'); + const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json')); + assert.equal(actual2.value.toString(), '{}'); }); test('create file under folder that does not exist', async () => { - const resource = joinPath(userDataResource, 'snippets/settings.json'); + const resource = joinPath(environmentService.snippetsHome, 'settings.json'); const actual1 = await testObject.createFile(resource, VSBuffer.fromString('{}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual2 = await pfs.readFile(path.join(userDataPath, 'snippets', 'settings.json')); - assert.equal(actual2, '{}'); + const actual2 = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json')); + assert.equal(actual2.value.toString(), '{}'); }); test('write to not existing file under container that exists', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); - const resource = joinPath(userDataResource, 'snippets/settings.json'); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); + const resource = joinPath(environmentService.snippetsHome, 'settings.json'); const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual = await pfs.readFile(path.join(userDataPath, 'snippets', 'settings.json')); - assert.equal(actual, '{}'); + const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json')); + assert.equal(actual.value.toString(), '{}'); }); test('write to not existing file under container that does not exists', async () => { - const resource = joinPath(userDataResource, 'snippets/settings.json'); + const resource = joinPath(environmentService.snippetsHome, 'settings.json'); const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual = await pfs.readFile(path.join(userDataPath, 'snippets', 'settings.json')); - assert.equal(actual, '{}'); + const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json')); + assert.equal(actual.value.toString(), '{}'); }); test('write to existing file under container', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); - await pfs.writeFile(path.join(userDataPath, 'snippets', 'settings.json'), '{}'); - const resource = joinPath(userDataResource, 'snippets/settings.json'); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}')); + const resource = joinPath(environmentService.snippetsHome, 'settings.json'); const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{a:1}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual = await pfs.readFile(path.join(userDataPath, 'snippets', 'settings.json')); - assert.equal(actual.toString(), '{a:1}'); + const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json')); + assert.equal(actual.value.toString(), '{a:1}'); }); test('write file under sub container', async () => { - const resource = joinPath(userDataResource, 'snippets/java/settings.json'); + const resource = joinPath(environmentService.snippetsHome, 'java/settings.json'); const actual1 = await testObject.writeFile(resource, VSBuffer.fromString('{}')); assert.equal(actual1.resource.toString(), resource.toString()); - const actual = await pfs.readFile(path.join(userDataPath, 'snippets', 'java', 'settings.json')); - assert.equal(actual, '{}'); + const actual = await testObject.readFile(joinPath(userDataHomeOnDisk, 'snippets', 'java', 'settings.json')); + assert.equal(actual.value.toString(), '{}'); }); test('delete throws error for folder that does not exist', async () => { try { - await testObject.del(joinPath(userDataResource, 'snippets')); + await testObject.del(environmentService.snippetsHome); assert.fail('Should fail the folder does not exist'); } catch (e) { } }); test('delete not existing file under container that exists', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); try { - await testObject.del(joinPath(userDataResource, 'snippets/settings.json')); + await testObject.del(joinPath(environmentService.snippetsHome, 'settings.json')); assert.fail('Should fail since file does not exist'); } catch (e) { } }); test('delete not existing file under container that does not exists', async () => { try { - await testObject.del(joinPath(userDataResource, 'snippets/settings.json')); + await testObject.del(joinPath(environmentService.snippetsHome, 'settings.json')); assert.fail('Should fail since file does not exist'); } catch (e) { } }); test('delete existing file under folder', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); - await pfs.writeFile(path.join(userDataPath, 'snippets', 'settings.json'), '{}'); - await testObject.del(joinPath(userDataResource, 'snippets/settings.json')); - const exists = await pfs.exists(path.join(userDataPath, 'snippets', 'settings.json')); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}')); + await testObject.del(joinPath(environmentService.snippetsHome, 'settings.json')); + const exists = await testObject.exists(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json')); assert.equal(exists, false); }); test('resolve folder', async () => { - await pfs.mkdirp(path.join(userDataPath, 'snippets')); - await pfs.writeFile(path.join(userDataPath, 'snippets', 'settings.json'), '{}'); - const result = await testObject.resolve(joinPath(userDataResource, 'snippets')); + await testObject.createFolder(joinPath(userDataHomeOnDisk, 'snippets')); + await testObject.writeFile(joinPath(userDataHomeOnDisk, 'snippets', 'settings.json'), VSBuffer.fromString('{}')); + const result = await testObject.resolve(environmentService.snippetsHome); assert.ok(result.isDirectory); assert.ok(result.children !== undefined); assert.equal(result.children!.length, 1); - assert.equal(result.children![0].resource.toString(), joinPath(userDataResource, 'snippets/settings.json').toString()); + assert.equal(result.children![0].resource.toString(), joinPath(environmentService.snippetsHome, 'settings.json').toString()); }); test('read backup file', async () => { - await pfs.writeFile(path.join(backupsPath, 'backup.json'), '{}'); - const result = await testObject.readFile(joinPath(userDataResource, `${BACKUPS}/backup.json`)); + await testObject.writeFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'), VSBuffer.fromString('{}')); + const result = await testObject.readFile(joinPath(environmentService.backupWorkspaceHome!, `backup.json`)); assert.equal(result.value, '{}'); }); test('create backup file', async () => { - await testObject.createFile(joinPath(userDataResource, `${BACKUPS}/backup.json`), VSBuffer.fromString('{}')); - const result = await pfs.readFile(path.join(backupsPath, 'backup.json')); - assert.equal(result, '{}'); + await testObject.createFile(joinPath(environmentService.backupWorkspaceHome!, `backup.json`), VSBuffer.fromString('{}')); + const result = await testObject.readFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json')); + assert.equal(result.value.toString(), '{}'); }); test('write backup file', async () => { - await pfs.writeFile(path.join(backupsPath, 'backup.json'), '{}'); - await testObject.writeFile(joinPath(userDataResource, `${BACKUPS}/backup.json`), VSBuffer.fromString('{a:1}')); - const result = await pfs.readFile(path.join(backupsPath, 'backup.json')); - assert.equal(result, '{a:1}'); + await testObject.writeFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'), VSBuffer.fromString('{}')); + await testObject.writeFile(joinPath(environmentService.backupWorkspaceHome!, `backup.json`), VSBuffer.fromString('{a:1}')); + const result = await testObject.readFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json')); + assert.equal(result.value.toString(), '{a:1}'); }); test('resolve backups folder', async () => { - await pfs.writeFile(path.join(backupsPath, 'backup.json'), '{}'); - const result = await testObject.resolve(joinPath(userDataResource, BACKUPS)); + await testObject.writeFile(joinPath(backupWorkspaceHomeOnDisk, 'backup.json'), VSBuffer.fromString('{}')); + const result = await testObject.resolve(environmentService.backupWorkspaceHome!); assert.ok(result.isDirectory); assert.ok(result.children !== undefined); assert.equal(result.children!.length, 1); - assert.equal(result.children![0].resource.toString(), joinPath(userDataResource, `${BACKUPS}/backup.json`).toString()); + assert.equal(result.children![0].resource.toString(), joinPath(environmentService.backupWorkspaceHome!, `backup.json`).toString()); }); }); @@ -315,7 +305,7 @@ suite('FileUserDataProvider - Watching', () => { let testObject: IFileService; let localBackupsResource: URI; let localUserDataResource: URI; - let userDataResource: URI; + let environmentService: IWorkbenchEnvironmentService; const disposables = new DisposableStore(); const fileEventEmitter: Emitter = new Emitter(); @@ -323,15 +313,11 @@ suite('FileUserDataProvider - Watching', () => { setup(() => { - const rootPath = path.join(os.tmpdir(), 'vsctests', uuid.generateUuid()); - const userDataPath = path.join(rootPath, 'user'); - const backupsPath = path.join(rootPath, BACKUPS); - localBackupsResource = URI.file(backupsPath); - localUserDataResource = URI.file(userDataPath); - userDataResource = localUserDataResource.with({ scheme: Schemas.userData }); + environmentService = new BrowserWorkbenchEnvironmentService({ remoteAuthority: 'remote', workspaceId: 'workspaceId', logsPath: URI.file('logFile') }); - const environmentService = new TestBrowserWorkbenchEnvironmentService({ remoteAuthority: 'remote', workspaceId: 'workspaceId', logsPath: URI.file('logFile') }); - environmentService.testUserRoamingDataHome = userDataResource; + const rootResource = URI.file(path.join(os.tmpdir(), 'vsctests', uuid.generateUuid())); + localUserDataResource = joinPath(rootResource, 'user'); + localBackupsResource = joinPath(rootResource, 'Backups'); const userDataFileSystemProvider = new FileUserDataProvider(localUserDataResource, localBackupsResource, new TestFileSystemProvider(fileEventEmitter.event), environmentService, new NullLogService()); disposables.add(userDataFileSystemProvider); @@ -341,12 +327,10 @@ suite('FileUserDataProvider - Watching', () => { disposables.add(testObject.registerProvider(Schemas.userData, userDataFileSystemProvider)); }); - teardown(() => { - disposables.clear(); - }); + teardown(() => disposables.clear()); test('file added change event', done => { - const expected = joinPath(userDataResource, 'settings.json'); + const expected = environmentService.settingsResource; const target = joinPath(localUserDataResource, 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.ADDED)) { @@ -360,7 +344,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('file updated change event', done => { - const expected = joinPath(userDataResource, 'settings.json'); + const expected = environmentService.settingsResource; const target = joinPath(localUserDataResource, 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.UPDATED)) { @@ -374,7 +358,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('file deleted change event', done => { - const expected = joinPath(userDataResource, 'settings.json'); + const expected = environmentService.settingsResource; const target = joinPath(localUserDataResource, 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.DELETED)) { @@ -388,7 +372,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('file under folder created change event', done => { - const expected = joinPath(userDataResource, 'snippets', 'settings.json'); + const expected = joinPath(environmentService.snippetsHome, 'settings.json'); const target = joinPath(localUserDataResource, 'snippets', 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.ADDED)) { @@ -402,7 +386,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('file under folder updated change event', done => { - const expected = joinPath(userDataResource, 'snippets', 'settings.json'); + const expected = joinPath(environmentService.snippetsHome, 'settings.json'); const target = joinPath(localUserDataResource, 'snippets', 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.UPDATED)) { @@ -416,7 +400,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('file under folder deleted change event', done => { - const expected = joinPath(userDataResource, 'snippets', 'settings.json'); + const expected = joinPath(environmentService.snippetsHome, 'settings.json'); const target = joinPath(localUserDataResource, 'snippets', 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.DELETED)) { @@ -444,7 +428,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('backup file created change event', done => { - const expected = joinPath(userDataResource, BACKUPS, 'settings.json'); + const expected = joinPath(environmentService.backupWorkspaceHome!, 'settings.json'); const target = joinPath(localBackupsResource, 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.ADDED)) { @@ -458,7 +442,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('backup file update change event', done => { - const expected = joinPath(userDataResource, BACKUPS, 'settings.json'); + const expected = joinPath(environmentService.backupWorkspaceHome!, 'settings.json'); const target = joinPath(localBackupsResource, 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.UPDATED)) { @@ -472,7 +456,7 @@ suite('FileUserDataProvider - Watching', () => { }); test('backup file delete change event', done => { - const expected = joinPath(userDataResource, BACKUPS, 'settings.json'); + const expected = joinPath(environmentService.backupWorkspaceHome!, 'settings.json'); const target = joinPath(localBackupsResource, 'settings.json'); testObject.onDidFilesChange(e => { if (e.contains(expected, FileChangeType.DELETED)) { diff --git a/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts b/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts index 61b87ae61ef..a03c1809c8d 100644 --- a/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/electron-sandbox/workspaceEditingService.ts @@ -13,7 +13,6 @@ import { WorkspaceService } from 'vs/workbench/services/configuration/browser/co import { IStorageService } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; -import { toBackupWorkspaceResource } from 'vs/workbench/services/backup/electron-sandbox/backup'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { basename } from 'vs/base/common/resources'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; @@ -173,7 +172,6 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi // Reinitialize backup service this.environmentService.configuration.backupPath = result.backupPath; - this.environmentService.configuration.backupWorkspaceResource = result.backupPath ? toBackupWorkspaceResource(result.backupPath, this.environmentService) : undefined; if (this.backupFileService instanceof BackupFileService) { this.backupFileService.reinitialize(); } From 784c1dad1568272a461c702fe4885e779503e83d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Sep 2020 15:44:40 +0200 Subject: [PATCH 28/98] use MessageChannel api to communicate between worker extension host and main thread --- .../browser/webWorkerExtensionHost.ts | 56 +++++++++++++++---- .../extensions/common/webWorkerIframe.ts | 16 +----- .../extensions/worker/extensionHostWorker.ts | 13 +++-- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index 6b672330aba..8740402bd1c 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -28,6 +28,7 @@ import { localize } from 'vs/nls'; import { generateUuid } from 'vs/base/common/uuid'; import { canceled, onUnexpectedError } from 'vs/base/common/errors'; import { WEB_WORKER_IFRAME } from 'vs/workbench/services/extensions/common/webWorkerIframe'; +import { Barrier } from 'vs/base/common/async'; export interface IWebWorkerExtensionHostInitData { readonly autoStart: boolean; @@ -82,7 +83,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost return this._protocolPromise; } - private _startInsideIframe(): Promise { + private async _startInsideIframe(): Promise { const emitter = this._register(new Emitter()); const iframe = document.createElement('iframe'); @@ -111,6 +112,9 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost const iframeContent = `data:text/html;charset=utf-8,${encodeURIComponent(html)}`; iframe.setAttribute('src', iframeContent); + const barrier = new Barrier(); + let port!: MessagePort; + this._register(dom.addDisposableListener(window, 'message', (event) => { if (event.source !== iframe.contentWindow) { return; @@ -129,38 +133,68 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost return; } const { data } = event.data; + if (barrier.isOpen() || !(data instanceof MessagePort)) { + console.warn('UNEXPECTED message', event); + this._onDidExit.fire([81, 'UNEXPECTED message']); + return; + } + port = data; + barrier.open(); + })); + + document.body.appendChild(iframe); + this._register(toDisposable(() => iframe.remove())); + + // await MessagePort and use it to directly communicate + // with the worker extension host + await barrier.wait(); + + port.onmessage = (event) => { + const { data } = event; if (!(data instanceof ArrayBuffer)) { console.warn('UNKNOWN data received', data); this._onDidExit.fire([77, 'UNKNOWN data received']); return; } emitter.fire(VSBuffer.wrap(new Uint8Array(data, 0, data.byteLength))); - })); + }; const protocol: IMessagePassingProtocol = { onMessage: emitter.event, send: vsbuf => { const data = vsbuf.buffer.buffer.slice(vsbuf.buffer.byteOffset, vsbuf.buffer.byteOffset + vsbuf.buffer.byteLength); - iframe.contentWindow!.postMessage({ - vscodeWebWorkerExtHostId, - data: data - }, '*', [data]); + port.postMessage(data, [data]); } }; - document.body.appendChild(iframe); - this._register(toDisposable(() => iframe.remove())); - return this._performHandshake(protocol); } - private _startOutsideIframe(): Promise { + private async _startOutsideIframe(): Promise { const emitter = new Emitter(); const url = getWorkerBootstrapUrl(require.toUrl('../worker/extensionHostWorkerMain.js'), 'WorkerExtensionHost'); const worker = new Worker(url, { name: 'WorkerExtensionHost' }); + const barrier = new Barrier(); + let port!: MessagePort; + worker.onmessage = (event) => { + const { data } = event; + if (barrier.isOpen() || !(data instanceof MessagePort)) { + console.warn('UNEXPECTED message', event); + this._onDidExit.fire([81, 'UNEXPECTED message']); + return; + } + port = data; + barrier.open(); + }; + + // await MessagePort and use it to directly communicate + // with the worker extension host + await barrier.wait(); + + port.onmessage = (event) => { const { data } = event; if (!(data instanceof ArrayBuffer)) { console.warn('UNKNOWN data received', data); @@ -184,7 +218,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost onMessage: emitter.event, send: vsbuf => { const data = vsbuf.buffer.buffer.slice(vsbuf.buffer.byteOffset, vsbuf.buffer.byteOffset + vsbuf.buffer.byteLength); - worker.postMessage(data, [data]); + port.postMessage(data, [data]); } }; diff --git a/src/vs/workbench/services/extensions/common/webWorkerIframe.ts b/src/vs/workbench/services/extensions/common/webWorkerIframe.ts index bf4731d3909..7b354788d46 100644 --- a/src/vs/workbench/services/extensions/common/webWorkerIframe.ts +++ b/src/vs/workbench/services/extensions/common/webWorkerIframe.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ export const WEB_WORKER_IFRAME = { - sha: 'sha256-rSINb5Ths99Zj4Ml59jEdHS4WbO+H5Iw+oyRmyi2MLw=', + sha: 'sha256-r24mDVsMuFEo8ChaY9ppVJKbY3CUM4I12Aw/yscWZbg=', js: ` (function() { const workerSrc = document.getElementById('vscode-worker-src').getAttribute('data-value'); @@ -13,8 +13,8 @@ export const WEB_WORKER_IFRAME = { worker.onmessage = (event) => { const { data } = event; - if (!(data instanceof ArrayBuffer)) { - console.warn('Unknown data received', data); + if (!(data instanceof MessagePort)) { + console.warn('Unknown data received', event); window.parent.postMessage({ vscodeWebWorkerExtHostId, error: { @@ -42,16 +42,6 @@ export const WEB_WORKER_IFRAME = { } }, '*'); }; - - window.addEventListener('message', function(event) { - if (event.source !== window.parent) { - return; - } - if (event.data.vscodeWebWorkerExtHostId !== vscodeWebWorkerExtHostId) { - return; - } - worker.postMessage(event.data.data, [event.data.data]); - }, false); })(); ` }; diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts index c1e85e6539f..3cffe4e2062 100644 --- a/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts +++ b/src/vs/workbench/services/extensions/worker/extensionHostWorker.ts @@ -33,7 +33,7 @@ self.close = () => console.trace(`'close' has been blocked`); const nativePostMessage = postMessage.bind(self); self.postMessage = () => console.trace(`'postMessage' has been blocked`); -const nativeAddEventLister = addEventListener.bind(self); +// const nativeAddEventLister = addEventListener.bind(self); self.addEventLister = () => console.trace(`'addEventListener' has been blocked`); (self)['AMDLoader'] = undefined; @@ -79,11 +79,14 @@ class ExtensionWorker { constructor() { - let emitter = new Emitter(); + const channel = new MessageChannel(); + const emitter = new Emitter(); let terminating = false; + // send over port2, keep port1 + nativePostMessage(channel.port2, [channel.port2]); - nativeAddEventLister('message', event => { + channel.port1.onmessage = event => { const { data } = event; if (!(data instanceof ArrayBuffer)) { console.warn('UNKNOWN data received', data); @@ -100,14 +103,14 @@ class ExtensionWorker { // emit non-terminate messages to the outside emitter.fire(msg); - }); + }; this.protocol = { onMessage: emitter.event, send: vsbuf => { if (!terminating) { const data = vsbuf.buffer.buffer.slice(vsbuf.buffer.byteOffset, vsbuf.buffer.byteOffset + vsbuf.buffer.byteLength); - nativePostMessage(data, [data]); + channel.port1.postMessage(data, [data]); } } }; From ee2ba80107b62e2d677bd284000605faf2928115 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Sep 2020 16:31:32 +0200 Subject: [PATCH 29/98] add cmd+i (mac), ctrl+i (linux/win) as additional intellisense trigger character, https://github.com/microsoft/vscode/issues/105207 --- src/vs/editor/contrib/suggest/suggestController.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index 3b92a21d7cc..9478f92d212 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -598,7 +598,8 @@ export class TriggerSuggestAction extends EditorAction { kbOpts: { kbExpr: EditorContextKeys.textInputFocus, primary: KeyMod.CtrlCmd | KeyCode.Space, - mac: { primary: KeyMod.WinCtrl | KeyCode.Space, secondary: [KeyMod.Alt | KeyCode.Escape] }, + secondary: [KeyMod.CtrlCmd | KeyCode.KEY_I], + mac: { primary: KeyMod.WinCtrl | KeyCode.Space, secondary: [KeyMod.Alt | KeyCode.Escape, KeyMod.CtrlCmd | KeyCode.KEY_I] }, weight: KeybindingWeight.EditorContrib } }); From 5cd1eff6040ec6cd8659a7a753b597fed06a6206 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 7 Sep 2020 16:47:30 +0200 Subject: [PATCH 30/98] Update grammars --- extensions/java/cgmanifest.json | 4 +- extensions/java/syntaxes/java.tmLanguage.json | 4 +- extensions/php/cgmanifest.json | 2 +- extensions/php/syntaxes/php.tmLanguage.json | 37 ++++++++++++++++++- extensions/sql/cgmanifest.json | 2 +- extensions/sql/syntaxes/sql.tmLanguage.json | 2 +- 6 files changed, 43 insertions(+), 8 deletions(-) diff --git a/extensions/java/cgmanifest.json b/extensions/java/cgmanifest.json index 7f0ef8760a8..68e15fac2df 100644 --- a/extensions/java/cgmanifest.json +++ b/extensions/java/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "atom/language-java", "repositoryUrl": "https://github.com/atom/language-java", - "commitHash": "2e179ceac423403eb5bf0eff26884093c3edba6f" + "commitHash": "f631536a4137d65b622f01cebeac72345f9e6f70" } }, "license": "MIT", - "version": "0.31.4" + "version": "0.31.5" } ], "version": 1 diff --git a/extensions/java/syntaxes/java.tmLanguage.json b/extensions/java/syntaxes/java.tmLanguage.json index 3cfa6f56337..11b6cf50a93 100644 --- a/extensions/java/syntaxes/java.tmLanguage.json +++ b/extensions/java/syntaxes/java.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-java/commit/2e179ceac423403eb5bf0eff26884093c3edba6f", + "version": "https://github.com/atom/language-java/commit/f631536a4137d65b622f01cebeac72345f9e6f70", "name": "Java", "scopeName": "source.java", "patterns": [ @@ -1785,7 +1785,7 @@ ] }, "variables": { - "begin": "(?x)\n(?=\n (\n \\b(void|boolean|byte|char|short|int|float|long|double)\\b\n |\n (?>(\\w+\\.)*[A-Z_]+\\w*) # e.g. `javax.ws.rs.Response`, or `String`\n )\n \\s*\n (\n <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List`\n )?\n \\s*\n (\n (\\[\\])* # int[][]\n )?\n \\s+\n [A-Za-z_$][\\w$]* # At least one identifier after space\n ([\\w\\[\\],$][\\w\\[\\],\\s]*)? # possibly primitive array or additional identifiers\n \\s*(=|:|;)\n)", + "begin": "(?x)\n(?=\n \\b\n (\n (void|boolean|byte|char|short|int|float|long|double)\n |\n (?>(\\w+\\.)*[A-Z_]+\\w*) # e.g. `javax.ws.rs.Response`, or `String`\n )\n \\b\n \\s*\n (\n <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List`\n )?\n \\s*\n (\n (\\[\\])* # int[][]\n )?\n \\s+\n [A-Za-z_$][\\w$]* # At least one identifier after space\n ([\\w\\[\\],$][\\w\\[\\],\\s]*)? # possibly primitive array or additional identifiers\n \\s*(=|:|;)\n)", "end": "(?=\\=|:|;)", "name": "meta.definition.variable.java", "patterns": [ diff --git a/extensions/php/cgmanifest.json b/extensions/php/cgmanifest.json index ea157efc34e..3c5b9b9ffd3 100644 --- a/extensions/php/cgmanifest.json +++ b/extensions/php/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "language-php", "repositoryUrl": "https://github.com/atom/language-php", - "commitHash": "11cdaf62a9d949d3aca550f1a58c9754de6b5ab0" + "commitHash": "6c0da475f86b45ea990638525f68be7658986546" } }, "license": "MIT", diff --git a/extensions/php/syntaxes/php.tmLanguage.json b/extensions/php/syntaxes/php.tmLanguage.json index a995a1e82ab..54fbd4b7869 100644 --- a/extensions/php/syntaxes/php.tmLanguage.json +++ b/extensions/php/syntaxes/php.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/atom/language-php/commit/11cdaf62a9d949d3aca550f1a58c9754de6b5ab0", + "version": "https://github.com/atom/language-php/commit/6c0da475f86b45ea990638525f68be7658986546", "scopeName": "source.php", "patterns": [ { @@ -1329,6 +1329,17 @@ } ] }, + "named-arguments": { + "match": "(?i)(?<=^|\\(|,)\\s*([a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)\\s*(:)(?!:)", + "captures": { + "1": { + "name": "entity.name.variable.parameter.php" + }, + "2": { + "name": "punctuation.separator.colon.php" + } + } + }, "function-call": { "patterns": [ { @@ -1357,6 +1368,9 @@ }, "name": "meta.function-call.php", "patterns": [ + { + "include": "#named-arguments" + }, { "include": "$self" } @@ -1395,6 +1409,9 @@ }, "name": "meta.function-call.php", "patterns": [ + { + "include": "#named-arguments" + }, { "include": "$self" } @@ -2242,6 +2259,9 @@ }, "name": "meta.method-call.php", "patterns": [ + { + "include": "#named-arguments" + }, { "include": "$self" } @@ -2614,6 +2634,9 @@ }, "name": "meta.method-call.static.php", "patterns": [ + { + "include": "#named-arguments" + }, { "include": "$self" } @@ -3447,6 +3470,18 @@ } }, "patterns": [ + { + "match": "(?i)^\\s*([a-z_\\x{7f}-\\x{7fffffff}][a-z0-9_\\x{7f}-\\x{7fffffff}]*)\\s*(?=:(?!:))", + "captures": { + "1": { + "patterns": [ + { + "include": "$self" + } + ] + } + } + }, { "include": "$self" } diff --git a/extensions/sql/cgmanifest.json b/extensions/sql/cgmanifest.json index 3ef90a09d14..45e7c7f4e7b 100644 --- a/extensions/sql/cgmanifest.json +++ b/extensions/sql/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "Microsoft/vscode-mssql", "repositoryUrl": "https://github.com/Microsoft/vscode-mssql", - "commitHash": "750d30dc48c4c0317b63bb5f1ed3e71487bb84a1" + "commitHash": "61ae0eb21ac53883a23e09913a5ae77a59126ff9" } }, "license": "MIT", diff --git a/extensions/sql/syntaxes/sql.tmLanguage.json b/extensions/sql/syntaxes/sql.tmLanguage.json index bc3b533bcb9..de4dc029f80 100644 --- a/extensions/sql/syntaxes/sql.tmLanguage.json +++ b/extensions/sql/syntaxes/sql.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/Microsoft/vscode-mssql/commit/750d30dc48c4c0317b63bb5f1ed3e71487bb84a1", + "version": "https://github.com/Microsoft/vscode-mssql/commit/61ae0eb21ac53883a23e09913a5ae77a59126ff9", "name": "SQL", "scopeName": "source.sql", "patterns": [ From 8a06771005baab7dda896f9515c040b39bad19d0 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Mon, 7 Sep 2020 16:52:13 +0200 Subject: [PATCH 31/98] readonly-ness, readonly over getter, some member sorting (properties, ctor, methods), https://github.com/microsoft/vscode/issues/105735 --- .../common/model/notebookTextModel.ts | 75 +++++++++++-------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index fbbd406c807..a98f8dace0b 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -103,30 +103,23 @@ export class NotebookOperationManager { export class NotebookTextModel extends Disposable implements INotebookTextModel { - private _cellhandlePool: number = 0; - private readonly _onWillDispose: Emitter = this._register(new Emitter()); - readonly onWillDispose: Event = this._onWillDispose.event; private readonly _onDidChangeCells = this._register(new Emitter<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>()); - get onDidChangeCells() { return this._onDidChangeCells.event; } - private readonly _emitSelections = this._register(new Emitter()); - get emitSelections() { return this._emitSelections.event; } - private _onDidModelChangeProxy = this._register(new Emitter()); - get onDidModelChangeProxy(): Event { return this._onDidModelChangeProxy.event; } - private _onDidSelectionChangeProxy = this._register(new Emitter()); - get onDidSelectionChange(): Event { return this._onDidSelectionChangeProxy.event; } - private _onDidChangeContent = this._register(new Emitter()); - onDidChangeContent: Event = this._onDidChangeContent.event; - private _onDidChangeMetadata = this._register(new Emitter()); - onDidChangeMetadata: Event = this._onDidChangeMetadata.event; + private readonly _onDidModelChangeProxy = this._register(new Emitter()); + private readonly _onDidChangeContent = this._register(new Emitter()); + private readonly _onDidChangeMetadata = this._register(new Emitter()); + + readonly onWillDispose: Event = this._onWillDispose.event; + readonly onDidChangeCells = this._onDidChangeCells.event; + readonly onDidModelChangeProxy = this._onDidModelChangeProxy.event; + readonly onDidChangeContent = this._onDidChangeContent.event; + readonly onDidChangeMetadata = this._onDidChangeMetadata.event; + + private _cellhandlePool: number = 0; private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); private _cells: NotebookCellTextModel[]; - get cells(): readonly NotebookCellTextModel[] { - return this._cells; - } - private _languages: string[] = []; private _allLanguages: boolean = false; @@ -147,9 +140,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel private _isUntitled: boolean | undefined = undefined; private _versionId = 0; - get versionId() { - return this._versionId; - } + //#region selection TODO@rebornix this shouldn't be here + + private readonly _emitSelections = this._register(new Emitter()); + readonly emitSelections = this._emitSelections.event; + private _onDidSelectionChangeProxy = this._register(new Emitter()); + readonly onDidSelectionChange = this._onDidSelectionChangeProxy.event; + private _selections: number[] = []; @@ -162,11 +159,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidSelectionChangeProxy.fire(this._selections); } + //#endregion + private _dirty = false; protected readonly _onDidChangeDirty = this._register(new Emitter()); readonly onDidChangeDirty = this._onDidChangeDirty.event; - private _operationManager: NotebookOperationManager; + private readonly _operationManager: NotebookOperationManager; constructor( readonly viewType: string, @@ -182,6 +181,21 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._operationManager = new NotebookOperationManager(this._undoService, uri); } + dispose() { + this._onWillDispose.fire(); + dispose(this._cellListeners.values()); + dispose(this._cells); + super.dispose(); + } + + get cells(): readonly NotebookCellTextModel[] { + return this._cells; + } + + get versionId() { + return this._versionId; + } + get isDirty() { return this._dirty; } @@ -261,12 +275,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel break; case CellEditType.Output: //TODO@joh,@rebornix no event, no undo stop (?) - this.assertIndex(edit.index); + this._assertCellIndex(edit.index); const cell = this._cells[edit.index]; this.spliceNotebookCellOutputs(cell.handle, [[0, cell.outputs.length, edit.outputs]]); break; case CellEditType.Metadata: - this.assertIndex(edit.index); + this._assertCellIndex(edit.index); this.deltaCellMetadata(this._cells[edit.index].handle, edit.metadata); break; } @@ -498,8 +512,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } moveCellToIdx(index: number, length: number, newIdx: number, emitToExtHost: boolean = true) { - this.assertIndex(index); - this.assertIndex(newIdx); + this._assertCellIndex(index); + this._assertCellIndex(newIdx); const cells = this._cells.splice(index, length); this._cells.splice(newIdx, 0, ...cells); @@ -513,7 +527,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } } - assertIndex(index: number) { + private _assertCellIndex(index: number): void { if (index < 0 || index >= this._cells.length) { throw new Error(`model index out of range ${index}`); } @@ -751,10 +765,5 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } //#endregion - dispose() { - this._onWillDispose.fire(); - dispose(this._cellListeners.values()); - dispose(this._cells); - super.dispose(); - } + } From b8caf59d0c3e2b9a832dce2e823ad5c0dfac8a72 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Mon, 7 Sep 2020 17:28:38 +0200 Subject: [PATCH 32/98] adopt color scheme in host service --- src/vs/code/electron-main/window.ts | 5 +- .../browser/viewParts/lines/viewLine.ts | 12 ++--- src/vs/editor/common/view/viewContext.ts | 5 +- .../contrib/message/messageController.ts | 5 +- .../parameterHints/parameterHintsWidget.ts | 5 +- .../browser/inspectTokens/inspectTokens.ts | 5 +- .../browser/standaloneThemeServiceImpl.ts | 9 ++-- .../test/browser/standaloneLanguages.test.ts | 7 +-- src/vs/platform/electron/common/electron.ts | 3 +- .../electron-main/electronMainService.ts | 7 ++- src/vs/platform/theme/common/theme.ts | 16 ++++++ src/vs/platform/theme/common/themeService.ts | 15 ++---- .../theme/test/common/testThemeService.ts | 5 +- src/vs/platform/windows/common/windows.ts | 19 +------ .../browser/parts/editor/tabsTitleControl.ts | 5 +- .../browser/parts/statusbar/statusbarPart.ts | 5 +- src/vs/workbench/browser/style.ts | 5 +- .../inspectEditorTokens.ts | 5 +- .../contrib/scm/browser/scmViewPane.ts | 5 +- .../test/common/terminalColorRegistry.test.ts | 11 ++-- .../themes/browser/themes.contribution.ts | 8 +-- .../contrib/timeline/browser/timelinePane.ts | 5 +- .../contrib/views/browser/treeView.ts | 7 +-- .../contrib/webview/browser/themeing.ts | 7 +-- src/vs/workbench/electron-sandbox/window.ts | 8 +-- .../environment/browser/environmentService.ts | 5 +- .../workbench/services/host/browser/host.ts | 3 +- .../electron-sandbox/nativeHostService.ts | 3 +- .../themes/browser/workbenchThemeService.ts | 52 ++++++++----------- .../services/themes/common/colorThemeData.ts | 13 ++--- .../themes/common/workbenchThemeService.ts | 2 - .../test/browser/workbenchTestServices.ts | 5 +- .../electron-browser/workbenchTestServices.ts | 5 +- src/vs/workbench/workbench.web.api.ts | 9 +++- 34 files changed, 149 insertions(+), 137 deletions(-) create mode 100644 src/vs/platform/theme/common/theme.ts diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 0df1b6af683..40cbd5b9a43 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -15,7 +15,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import product from 'vs/platform/product/common/product'; -import { IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration, ColorScheme } from 'vs/platform/windows/common/windows'; +import { IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; @@ -34,6 +34,7 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IStorageMainService } from 'vs/platform/storage/node/storageMainService'; import { IFileService } from 'vs/platform/files/common/files'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export interface IWindowCreationOptions { state: IWindowState; @@ -784,7 +785,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { windowConfiguration.fullscreen = this.isFullScreen; // Set Accessibility Config - windowConfiguration.colorScheme = (nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors) ? ColorScheme.HIGH_CONTRAST : nativeTheme.shouldUseDarkColors ? ColorScheme.DARK : ColorScheme.DEFAULT; + windowConfiguration.colorScheme = (nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors) ? ColorScheme.HIGH_CONTRAST : nativeTheme.shouldUseDarkColors ? ColorScheme.DARK : ColorScheme.LIGHT; windowConfiguration.autoDetectHighContrast = windowConfig?.autoDetectHighContrast ?? true; windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled; diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index 65798b74acc..d75928f24ae 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -15,7 +15,7 @@ import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations'; import { CharacterMapping, ForeignElementType, RenderLineInput, renderViewLine, LineRange } from 'vs/editor/common/viewLayout/viewLineRenderer'; import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; -import { HIGH_CONTRAST, ThemeType } from 'vs/platform/theme/common/themeService'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; import { EditorOption, EditorFontLigatures } from 'vs/editor/common/config/editorOptions'; const canUseFastRenderedViewLine = (function () { @@ -71,7 +71,7 @@ export class DomReadingContext { } export class ViewLineOptions { - public readonly themeType: ThemeType; + public readonly themeType: ColorScheme; public readonly renderWhitespace: 'none' | 'boundary' | 'selection' | 'trailing' | 'all'; public readonly renderControlCharacters: boolean; public readonly spaceWidth: number; @@ -83,7 +83,7 @@ export class ViewLineOptions { public readonly stopRenderingLineAfter: number; public readonly fontLigatures: string; - constructor(config: IConfiguration, themeType: ThemeType) { + constructor(config: IConfiguration, themeType: ColorScheme) { this.themeType = themeType; const options = config.options; const fontInfo = options.get(EditorOption.fontInfo); @@ -163,7 +163,7 @@ export class ViewLine implements IVisibleLine { this._options = newOptions; } public onSelectionChanged(): boolean { - if (alwaysRenderInlineSelection || this._options.themeType === HIGH_CONTRAST || this._options.renderWhitespace === 'selection') { + if (alwaysRenderInlineSelection || this._options.themeType === ColorScheme.HIGH_CONTRAST || this._options.renderWhitespace === 'selection') { this._isMaybeInvalid = true; return true; } @@ -184,7 +184,7 @@ export class ViewLine implements IVisibleLine { // Only send selection information when needed for rendering whitespace let selectionsOnLine: LineRange[] | null = null; - if (alwaysRenderInlineSelection || options.themeType === HIGH_CONTRAST || this._options.renderWhitespace === 'selection') { + if (alwaysRenderInlineSelection || options.themeType === ColorScheme.HIGH_CONTRAST || this._options.renderWhitespace === 'selection') { const selections = viewportData.selections; for (const selection of selections) { @@ -197,7 +197,7 @@ export class ViewLine implements IVisibleLine { const endColumn = (selection.endLineNumber === lineNumber ? selection.endColumn : lineData.maxColumn); if (startColumn < endColumn) { - if (options.themeType === HIGH_CONTRAST || this._options.renderWhitespace !== 'selection') { + if (options.themeType === ColorScheme.HIGH_CONTRAST || this._options.renderWhitespace !== 'selection') { actualInlineDecorations.push(new LineDecoration(startColumn, endColumn, 'inline-selected-text', InlineDecorationType.Regular)); } else { if (!selectionsOnLine) { diff --git a/src/vs/editor/common/view/viewContext.ts b/src/vs/editor/common/view/viewContext.ts index 74628ebb857..b888fbec6ad 100644 --- a/src/vs/editor/common/view/viewContext.ts +++ b/src/vs/editor/common/view/viewContext.ts @@ -6,15 +6,16 @@ import { IConfiguration } from 'vs/editor/common/editorCommon'; import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; import { IViewLayout, IViewModel } from 'vs/editor/common/viewModel/viewModel'; -import { IColorTheme, ThemeType } from 'vs/platform/theme/common/themeService'; +import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Color } from 'vs/base/common/color'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export class EditorTheme { private _theme: IColorTheme; - public get type(): ThemeType { + public get type(): ColorScheme { return this._theme.type; } diff --git a/src/vs/editor/contrib/message/messageController.ts b/src/vs/editor/contrib/message/messageController.ts index e94a981d167..6bec24fd00f 100644 --- a/src/vs/editor/contrib/message/messageController.ts +++ b/src/vs/editor/contrib/message/messageController.ts @@ -15,9 +15,10 @@ import { registerEditorContribution, EditorCommand, registerEditorCommand } from import { ICodeEditor, IContentWidget, IContentWidgetPosition, ContentWidgetPositionPreference } from 'vs/editor/browser/editorBrowser'; import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IPosition } from 'vs/editor/common/core/position'; -import { registerThemingParticipant, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { inputValidationInfoBorder, inputValidationInfoBackground, inputValidationInfoForeground } from 'vs/platform/theme/common/colorRegistry'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export class MessageController extends Disposable implements IEditorContribution { @@ -184,7 +185,7 @@ registerEditorContribution(MessageController.ID, MessageController); registerThemingParticipant((theme, collector) => { const border = theme.getColor(inputValidationInfoBorder); if (border) { - let borderWidth = theme.type === HIGH_CONTRAST ? 2 : 1; + let borderWidth = theme.type === ColorScheme.HIGH_CONTRAST ? 2 : 1; collector.addRule(`.monaco-editor .monaco-editor-overlaymessage .anchor { border-top-color: ${border}; }`); collector.addRule(`.monaco-editor .monaco-editor-overlaymessage .message { border: ${borderWidth}px solid ${border}; }`); } diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts index c34c98c2f97..9a3cf05bb24 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts @@ -20,11 +20,12 @@ import * as nls from 'vs/nls'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { editorHoverBackground, editorHoverBorder, textCodeBlockBackground, textLinkForeground, editorHoverForeground } from 'vs/platform/theme/common/colorRegistry'; -import { HIGH_CONTRAST, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ParameterHintsModel, TriggerContext } from 'vs/editor/contrib/parameterHints/parameterHintsModel'; import { pad } from 'vs/base/common/strings'; import { registerIcon, Codicon } from 'vs/base/common/codicons'; import { assertIsDefined } from 'vs/base/common/types'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; const $ = dom.$; @@ -364,7 +365,7 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget { registerThemingParticipant((theme, collector) => { const border = theme.getColor(editorHoverBorder); if (border) { - const borderWidth = theme.type === HIGH_CONTRAST ? 2 : 1; + const borderWidth = theme.type === ColorScheme.HIGH_CONTRAST ? 2 : 1; collector.addRule(`.monaco-editor .parameter-hints-widget { border: ${borderWidth}px solid ${border}; }`); collector.addRule(`.monaco-editor .parameter-hints-widget.multiple .body { border-left: 1px solid ${border.transparent(0.5)}; }`); collector.addRule(`.monaco-editor .parameter-hints-widget .signature.has-docs { border-bottom: 1px solid ${border.transparent(0.5)}; }`); diff --git a/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts b/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts index 31108f99ddb..192f9218551 100644 --- a/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts +++ b/src/vs/editor/standalone/browser/inspectTokens/inspectTokens.ts @@ -20,8 +20,9 @@ import { NULL_STATE, nullTokenize, nullTokenize2 } from 'vs/editor/common/modes/ import { IModeService } from 'vs/editor/common/services/modeService'; import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; import { editorHoverBackground, editorHoverBorder, editorHoverForeground } from 'vs/platform/theme/common/colorRegistry'; -import { HIGH_CONTRAST, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { InspectTokensNLS } from 'vs/editor/common/standaloneStrings'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; class InspectTokensController extends Disposable implements IEditorContribution { @@ -332,7 +333,7 @@ registerEditorAction(InspectTokens); registerThemingParticipant((theme, collector) => { const border = theme.getColor(editorHoverBorder); if (border) { - let borderWidth = theme.type === HIGH_CONTRAST ? 2 : 1; + let borderWidth = theme.type === ColorScheme.HIGH_CONTRAST ? 2 : 1; collector.addRule(`.monaco-editor .tokens-inspect-widget { border: ${borderWidth}px solid ${border}; }`); collector.addRule(`.monaco-editor .tokens-inspect-widget .tokens-inspect-separator { background-color: ${border}; }`); } diff --git a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts index 9e3f3ac0c9c..71d419567ee 100644 --- a/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts @@ -15,6 +15,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { ColorIdentifier, Extensions, IColorRegistry } from 'vs/platform/theme/common/colorRegistry'; import { Extensions as ThemingExtensions, ICssStyleCollector, IFileIconTheme, IThemingRegistry, ITokenStyle } from 'vs/platform/theme/common/themeService'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; const VS_THEME_NAME = 'vs'; const VS_DARK_THEME_NAME = 'vs-dark'; @@ -107,11 +108,11 @@ class StandaloneTheme implements IStandaloneTheme { return Object.prototype.hasOwnProperty.call(this.getColors(), colorId); } - public get type() { + public get type(): ColorScheme { switch (this.base) { - case VS_THEME_NAME: return 'light'; - case HC_BLACK_THEME_NAME: return 'hc'; - default: return 'dark'; + case VS_THEME_NAME: return ColorScheme.LIGHT; + case HC_BLACK_THEME_NAME: return ColorScheme.HIGH_CONTRAST; + default: return ColorScheme.DARK; } } diff --git a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts index 282422dcbd2..e3c7a31f160 100644 --- a/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts +++ b/src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts @@ -12,7 +12,8 @@ import { TokenTheme } from 'vs/editor/common/modes/supports/tokenization'; import { ILineTokens, IToken, TokenizationSupport2Adapter, TokensProvider } from 'vs/editor/standalone/browser/standaloneLanguages'; import { IStandaloneTheme, IStandaloneThemeData, IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; -import { IFileIconTheme, IColorTheme, LIGHT, ITokenStyle } from 'vs/platform/theme/common/themeService'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { IFileIconTheme, IColorTheme, ITokenStyle } from 'vs/platform/theme/common/themeService'; suite('TokenizationSupport2Adapter', () => { @@ -46,9 +47,9 @@ suite('TokenizationSupport2Adapter', () => { tokenTheme: new MockTokenTheme(), - themeName: LIGHT, + themeName: ColorScheme.LIGHT, - type: LIGHT, + type: ColorScheme.LIGHT, getColor: (color: ColorIdentifier, useDefault?: boolean): Color => { throw new Error('Not implemented'); diff --git a/src/vs/platform/electron/common/electron.ts b/src/vs/platform/electron/common/electron.ts index 80a07026191..90033410206 100644 --- a/src/vs/platform/electron/common/electron.ts +++ b/src/vs/platform/electron/common/electron.ts @@ -5,9 +5,10 @@ import { Event } from 'vs/base/common/event'; import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, MouseInputEvent } from 'vs/base/parts/sandbox/common/electronTypes'; -import { IOpenedWindow, IWindowOpenable, IOpenEmptyWindowOptions, IOpenWindowOptions, ColorScheme } from 'vs/platform/windows/common/windows'; +import { IOpenedWindow, IWindowOpenable, IOpenEmptyWindowOptions, IOpenWindowOptions } from 'vs/platform/windows/common/windows'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export interface IOSProperties { type: string; diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 4088e35ff58..21a2549ef51 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -8,7 +8,7 @@ import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-m import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, Menu, BrowserWindow, app, clipboard, powerMonitor, nativeTheme } from 'electron'; import { OpenContext } from 'vs/platform/windows/node/window'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; -import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions, ColorScheme } from 'vs/platform/windows/common/windows'; +import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; import { isMacintosh, isWindows, isRootUser } from 'vs/base/common/platform'; import { ICommonElectronService, IOSProperties } from 'vs/platform/electron/common/electron'; @@ -22,6 +22,7 @@ import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { MouseInputEvent } from 'vs/base/parts/sandbox/common/electronTypes'; import { arch, totalmem, release, platform, type } from 'os'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export interface IElectronMainService extends AddFirstParameterToFunctions /* only methods, not events */, number | undefined /* window ID */> { } @@ -45,11 +46,13 @@ export class ElectronMainService implements IElectronMainService { // Color Scheme changes nativeTheme.on('updated', () => { - let colorScheme = ColorScheme.DEFAULT; + let colorScheme; if (nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors) { colorScheme = ColorScheme.HIGH_CONTRAST; } else if (nativeTheme.shouldUseDarkColors) { colorScheme = ColorScheme.DARK; + } else { + colorScheme = ColorScheme.LIGHT; } this._onColorSchemeChange.fire(colorScheme); diff --git a/src/vs/platform/theme/common/theme.ts b/src/vs/platform/theme/common/theme.ts new file mode 100644 index 00000000000..843210bfeb5 --- /dev/null +++ b/src/vs/platform/theme/common/theme.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Color theme used by the OS and by color themes. + */ +export enum ColorScheme { + DARK = 'dark', + LIGHT = 'light', + HIGH_CONTRAST = 'hc' +} + + + diff --git a/src/vs/platform/theme/common/themeService.ts b/src/vs/platform/theme/common/themeService.ts index e33a3e9cbd4..e936a4eb05a 100644 --- a/src/vs/platform/theme/common/themeService.ts +++ b/src/vs/platform/theme/common/themeService.ts @@ -10,6 +10,7 @@ import * as platform from 'vs/platform/registry/common/platform'; import { ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Event, Emitter } from 'vs/base/common/event'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export const IThemeService = createDecorator('themeService'); @@ -65,16 +66,10 @@ export namespace ThemeIcon { export const FileThemeIcon = { id: 'file' }; export const FolderThemeIcon = { id: 'folder' }; -// base themes -export const DARK: ThemeType = 'dark'; -export const LIGHT: ThemeType = 'light'; -export const HIGH_CONTRAST: ThemeType = 'hc'; -export type ThemeType = 'light' | 'dark' | 'hc'; - -export function getThemeTypeSelector(type: ThemeType): string { +export function getThemeTypeSelector(type: ColorScheme): string { switch (type) { - case DARK: return 'vs-dark'; - case HIGH_CONTRAST: return 'hc-black'; + case ColorScheme.DARK: return 'vs-dark'; + case ColorScheme.HIGH_CONTRAST: return 'hc-black'; default: return 'vs'; } } @@ -88,7 +83,7 @@ export interface ITokenStyle { export interface IColorTheme { - readonly type: ThemeType; + readonly type: ColorScheme; readonly label: string; diff --git a/src/vs/platform/theme/test/common/testThemeService.ts b/src/vs/platform/theme/test/common/testThemeService.ts index bc5fc2403f1..2bdd34d8eb0 100644 --- a/src/vs/platform/theme/test/common/testThemeService.ts +++ b/src/vs/platform/theme/test/common/testThemeService.ts @@ -4,14 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import { Event, Emitter } from 'vs/base/common/event'; -import { IThemeService, IColorTheme, DARK, IFileIconTheme, ITokenStyle } from 'vs/platform/theme/common/themeService'; +import { IThemeService, IColorTheme, IFileIconTheme, ITokenStyle } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export class TestColorTheme implements IColorTheme { public readonly label = 'test'; - constructor(private colors: { [id: string]: string; } = {}, public type = DARK) { + constructor(private colors: { [id: string]: string; } = {}, public type = ColorScheme.DARK) { } getColor(color: string, useDefault?: boolean): Color | undefined { diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index bdb6fbdf7f9..60690f56c38 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -11,6 +11,7 @@ import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platf import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { LogLevel } from 'vs/platform/log/common/log'; import { ExportData } from 'vs/base/common/performance'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export interface IBaseOpenWindowsOptions { forceReuseWindow?: boolean; @@ -253,21 +254,3 @@ export interface INativeWindowConfiguration extends IWindowConfiguration, Native export function zoomLevelToZoomFactor(zoomLevel = 0): number { return Math.pow(1.2, zoomLevel); } - -export enum ColorScheme { - - /** - * The window should use standard colors. - */ - DEFAULT = 1, - - /** - * The window should use dark colors. - */ - DARK = 2, - - /** - * The window should use high contrast colors. - */ - HIGH_CONTRAST = 3 -} diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index f3eb689c73a..a1f2ceec6be 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -24,7 +24,7 @@ import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDispo import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { getOrSet } from 'vs/base/common/map'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BACKGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER } from 'vs/workbench/common/theme'; import { activeContrastBorder, contrastBorder, editorBackground, breadcrumbsBackground } from 'vs/platform/theme/common/colorRegistry'; import { ResourcesDropHandler, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, DragAndDropObserver } from 'vs/workbench/browser/dnd'; @@ -45,6 +45,7 @@ import { basenameOrAuthority } from 'vs/base/common/resources'; import { RunOnceScheduler } from 'vs/base/common/async'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { IPath, win32, posix } from 'vs/base/common/path'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; interface IEditorInputLabel { name?: string; @@ -1464,7 +1465,7 @@ export class TabsTitleControl extends TitleControl { registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { // Add border between tabs and breadcrumbs in high contrast mode. - if (theme.type === HIGH_CONTRAST) { + if (theme.type === ColorScheme.HIGH_CONTRAST) { const borderColor = (theme.getColor(TAB_BORDER) || theme.getColor(contrastBorder)); collector.addRule(` .monaco-workbench .part.editor > .content .editor-group-container > .title.tabs > .tabs-and-actions-container { diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index e29be7ab5a0..78cb764802d 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -15,7 +15,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/common/statusbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator } from 'vs/base/common/actions'; -import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeColor, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, ThemeColor } from 'vs/platform/theme/common/themeService'; import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; @@ -38,6 +38,7 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ServicesAccessor } from 'vs/editor/browser/editorExtensions'; import { RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; interface IPendingStatusbarEntry { id: string; @@ -889,7 +890,7 @@ class StatusbarEntryItem extends Disposable { } registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { - if (theme.type !== HIGH_CONTRAST) { + if (theme.type !== ColorScheme.HIGH_CONTRAST) { const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND); if (statusBarItemHoverBackground) { collector.addRule(`.monaco-workbench .part.statusbar > .items-container > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`); diff --git a/src/vs/workbench/browser/style.ts b/src/vs/workbench/browser/style.ts index d8a43a7ace3..c562af3bb9f 100644 --- a/src/vs/workbench/browser/style.ts +++ b/src/vs/workbench/browser/style.ts @@ -5,12 +5,13 @@ import 'vs/css!./media/style'; -import { registerThemingParticipant, IColorTheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { iconForeground, foreground, selectionBackground, focusBorder, scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, listHighlightForeground, inputPlaceholderForeground } from 'vs/platform/theme/common/colorRegistry'; import { WORKBENCH_BACKGROUND, TITLE_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme'; import { isWeb, isIOS, isMacintosh, isWindows } from 'vs/base/common/platform'; import { createMetaElement } from 'vs/base/browser/dom'; import { isSafari, isStandalone } from 'vs/base/browser/browser'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { @@ -127,7 +128,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = } // High Contrast theme overwrites for outline - if (theme.type === HIGH_CONTRAST) { + if (theme.type === ColorScheme.HIGH_CONTRAST) { collector.addRule(` .hc-black [tabindex="0"]:focus, .hc-black [tabindex="-1"]:focus, diff --git a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts index 16f632117f0..75138d4a33c 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts @@ -20,7 +20,7 @@ import { FontStyle, LanguageIdentifier, StandardTokenType, TokenMetadata, Docume import { IModeService } from 'vs/editor/common/services/modeService'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { editorHoverBackground, editorHoverBorder } from 'vs/platform/theme/common/colorRegistry'; -import { HIGH_CONTRAST, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; +import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { findMatchingThemeRule } from 'vs/workbench/services/textMate/common/TMHelper'; import { ITextMateService, IGrammar, IToken, StackElement } from 'vs/workbench/services/textMate/common/textMateService'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; @@ -29,6 +29,7 @@ import { ColorThemeData, TokenStyleDefinitions, TokenStyleDefinition, TextMateTh import { SemanticTokenRule, TokenStyleData, TokenStyle } from 'vs/platform/theme/common/tokenClassificationRegistry'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { SEMANTIC_HIGHLIGHTING_SETTING_ID, IEditorSemanticHighlightingOptions } from 'vs/editor/common/services/modelServiceImpl'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; const $ = dom.$; @@ -643,7 +644,7 @@ registerEditorAction(InspectEditorTokens); registerThemingParticipant((theme, collector) => { const border = theme.getColor(editorHoverBorder); if (border) { - let borderWidth = theme.type === HIGH_CONTRAST ? 2 : 1; + let borderWidth = theme.type === ColorScheme.HIGH_CONTRAST ? 2 : 1; collector.addRule(`.monaco-editor .token-inspect-widget { border: ${borderWidth}px solid ${border}; }`); collector.addRule(`.monaco-editor .token-inspect-widget .tiw-metadata-separator { background-color: ${border}; }`); } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index f2cec6d0813..70911617807 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -22,7 +22,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { MenuItemAction, IMenuService } from 'vs/platform/actions/common/actions'; import { IAction, IActionViewItem, ActionRunner, Action, RadioGroup, Separator, SubmenuAction, IActionViewItemProvider } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IThemeService, LIGHT, registerThemingParticipant, IFileIconTheme } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, IFileIconTheme } from 'vs/platform/theme/common/themeService'; import { isSCMResource, isSCMResourceGroup, connectPrimaryMenuToInlineActionBar, isSCMRepository, isSCMInput, collectContextMenuActions, StatusBarAction, StatusBarActionViewItem, getRepositoryVisibilityActions } from './util'; import { attachBadgeStyler } from 'vs/platform/theme/common/styler'; import { WorkbenchCompressibleObjectTree, IOpenEvent } from 'vs/platform/list/browser/listService'; @@ -75,6 +75,7 @@ import { Codicon } from 'vs/base/common/codicons'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { RepositoryRenderer } from 'vs/workbench/contrib/scm/browser/scmRepositoryRenderer'; import { IPosition } from 'vs/editor/common/core/position'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; type TreeElement = ISCMRepository | ISCMInput | ISCMResourceGroup | IResourceNode | ISCMResource; @@ -406,7 +407,7 @@ class ResourceRenderer implements ICompressibleTreeRenderer { const theme = this.themeService.getColorTheme(); - const icon = iconResource && (theme.type === LIGHT ? iconResource.decorations.icon : iconResource.decorations.iconDark); + const icon = iconResource && (theme.type === ColorScheme.LIGHT ? iconResource.decorations.icon : iconResource.decorations.iconDark); template.fileLabel.setFile(uri, { fileDecorations: { colors: false, badges: !icon }, diff --git a/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts b/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts index 48c52ffb3a8..9854f914413 100644 --- a/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts @@ -7,13 +7,14 @@ import * as assert from 'assert'; import { Extensions as ThemeingExtensions, IColorRegistry, ColorIdentifier } from 'vs/platform/theme/common/colorRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; import { ansiColorIdentifiers, registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; -import { IColorTheme, ThemeType } from 'vs/platform/theme/common/themeService'; +import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { Color } from 'vs/base/common/color'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; registerColors(); let themingRegistry = Registry.as(ThemeingExtensions.ColorContribution); -function getMockTheme(type: ThemeType): IColorTheme { +function getMockTheme(type: ColorScheme): IColorTheme { let theme = { selector: '', label: '', @@ -30,7 +31,7 @@ function getMockTheme(type: ThemeType): IColorTheme { suite('Workbench - TerminalColorRegistry', () => { test('hc colors', function () { - let theme = getMockTheme('hc'); + let theme = getMockTheme(ColorScheme.HIGH_CONTRAST); let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); assert.deepEqual(colors, [ @@ -55,7 +56,7 @@ suite('Workbench - TerminalColorRegistry', () => { }); test('light colors', function () { - let theme = getMockTheme('light'); + let theme = getMockTheme(ColorScheme.LIGHT); let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); assert.deepEqual(colors, [ @@ -80,7 +81,7 @@ suite('Workbench - TerminalColorRegistry', () => { }); test('dark colors', function () { - let theme = getMockTheme('dark'); + let theme = getMockTheme(ColorScheme.DARK); let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); assert.deepEqual(colors, [ diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index ff3a71ec746..dca30b971db 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -17,7 +17,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IColorRegistry, Extensions as ColorRegistryExtensions } from 'vs/platform/theme/common/colorRegistry'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Color } from 'vs/base/common/color'; -import { LIGHT, DARK, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; import { colorThemeSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IQuickInputService, QuickPickInput } from 'vs/platform/quickinput/common/quickInput'; @@ -45,9 +45,9 @@ export class SelectColorThemeAction extends Action { const currentTheme = this.themeService.getColorTheme(); const picks: QuickPickInput[] = [ - ...toEntries(themes.filter(t => t.type === LIGHT), localize('themes.category.light', "light themes")), - ...toEntries(themes.filter(t => t.type === DARK), localize('themes.category.dark', "dark themes")), - ...toEntries(themes.filter(t => t.type === HIGH_CONTRAST), localize('themes.category.hc', "high contrast themes")), + ...toEntries(themes.filter(t => t.type === ColorScheme.LIGHT), localize('themes.category.light', "light themes")), + ...toEntries(themes.filter(t => t.type === ColorScheme.DARK), localize('themes.category.dark', "dark themes")), + ...toEntries(themes.filter(t => t.type === ColorScheme.HIGH_CONTRAST), localize('themes.category.hc', "high contrast themes")), ...configurationEntries(this.extensionGalleryService, localize('installColorThemes', "Install Additional Color Themes...")) ]; diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 8ba8fc64af5..5eab72c696f 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -32,7 +32,7 @@ import { ITimelineService, TimelineChangeEvent, TimelineItem, TimelineOptions, T import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { SideBySideEditor, toResource } from 'vs/workbench/common/editor'; import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { IThemeService, LIGHT, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IProgressService } from 'vs/platform/progress/common/progress'; import { IOpenerService } from 'vs/platform/opener/common/opener'; @@ -41,6 +41,7 @@ import { MenuEntryActionViewItem, createAndFillInContextMenuActions, SubmenuEntr import { MenuItemAction, IMenuService, MenuId, registerAction2, Action2, MenuRegistry, SubmenuItemAction } from 'vs/platform/actions/common/actions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; const ItemHeight = 22; @@ -1117,7 +1118,7 @@ class TimelineTreeRenderer implements ITreeRenderer { - await this.lifecycleService.when(LifecyclePhase.Ready); - this.themeService.setOSHighContrast(scheme === ColorScheme.HIGH_CONTRAST); - })); - // accessibility support changed event ipcRenderer.on('vscode:accessibilitySupportChanged', (event: unknown, accessibilitySupportEnabled: boolean) => { this.accessibilityService.setAccessibilitySupport(accessibilitySupportEnabled ? AccessibilitySupport.Enabled : AccessibilitySupport.Disabled); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 17df4966d73..06e2baf7063 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -8,13 +8,14 @@ import { joinPath } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import { IExtensionHostDebugParams } from 'vs/platform/environment/common/environment'; -import { ColorScheme, IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows'; +import { IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkbenchConstructionOptions as IWorkbenchOptions } from 'vs/workbench/workbench.web.api'; import product from 'vs/platform/product/common/product'; import { memoize } from 'vs/base/common/decorators'; import { onUnexpectedError } from 'vs/base/common/errors'; import { parseLineAndColumnAware } from 'vs/base/common/extpath'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; class BrowserWorkbenchConfiguration implements IWindowConfiguration { @@ -76,7 +77,7 @@ class BrowserWorkbenchConfiguration implements IWindowConfiguration { return ColorScheme.DARK; } - return ColorScheme.DEFAULT; + return ColorScheme.LIGHT; } } diff --git a/src/vs/workbench/services/host/browser/host.ts b/src/vs/workbench/services/host/browser/host.ts index 8a0d724f07c..c10f8c651ac 100644 --- a/src/vs/workbench/services/host/browser/host.ts +++ b/src/vs/workbench/services/host/browser/host.ts @@ -5,7 +5,8 @@ import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IWindowOpenable, IOpenWindowOptions, IOpenEmptyWindowOptions, ColorScheme } from 'vs/platform/windows/common/windows'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { IWindowOpenable, IOpenWindowOptions, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; export const IHostService = createDecorator('hostService'); diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 49ed4a1e918..85cf4ab0827 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -9,8 +9,9 @@ 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, ColorScheme } from 'vs/platform/windows/common/windows'; +import { IWindowOpenable, IOpenWindowOptions, isFolderToOpen, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { Disposable } from 'vs/base/common/lifecycle'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export class NativeHostService extends Disposable implements IHostService { diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index ff15ab584c5..0c2813d013b 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -13,7 +13,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import * as errors from 'vs/base/common/errors'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ColorThemeData } from 'vs/workbench/services/themes/common/colorThemeData'; -import { IColorTheme, Extensions as ThemingExtensions, IThemingRegistry, ThemeType, LIGHT, DARK, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService'; +import { IColorTheme, Extensions as ThemingExtensions, IThemingRegistry } from 'vs/platform/theme/common/themeService'; import { Event, Emitter } from 'vs/base/common/event'; import { registerFileIconThemeSchemas } from 'vs/workbench/services/themes/common/fileIconThemeSchema'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; @@ -34,7 +34,9 @@ import { ProductIconThemeData, DEFAULT_PRODUCT_ICON_THEME_ID } from 'vs/workbenc import { registerProductIconThemeSchemas } from 'vs/workbench/services/themes/common/productIconThemeSchema'; import { ILogService } from 'vs/platform/log/common/log'; import { isWeb } from 'vs/base/common/platform'; -import { ColorScheme } from 'vs/platform/windows/common/windows'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { IHostService } from 'vs/workbench/services/host/browser/host'; + // implementation @@ -92,7 +94,6 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { private readonly onProductIconThemeChange: Emitter; private readonly productIconThemeWatcher: ThemeFileWatcher; - private isOSInHighContrast: boolean; // tracking the high contrast state of the OS eventauilly should go out to a seperate service private themeSettingIdBeforeSchemeSwitch: string | undefined; constructor( @@ -104,13 +105,12 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { @IFileService private readonly fileService: IFileService, @IExtensionResourceLoaderService private readonly extensionResourceLoaderService: IExtensionResourceLoaderService, @IWorkbenchLayoutService readonly layoutService: IWorkbenchLayoutService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @IHostService private readonly hostService: IHostService, ) { this.container = layoutService.container; this.settings = new ThemeConfiguration(configurationService); - this.isOSInHighContrast = environmentService.configuration.colorScheme === ColorScheme.HIGH_CONTRAST; - this.colorThemeRegistry = new ThemeRegistry(extensionService, colorThemesExtPoint, ColorThemeData.fromExtensionTheme); this.colorThemeWatcher = new ThemeFileWatcher(fileService, environmentService, this.reloadCurrentColorTheme.bind(this)); this.onColorThemeChange = new Emitter({ leakWarningThreshold: 400 }); @@ -144,7 +144,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { } } if (!themeData) { - themeData = ColorThemeData.createUnloadedThemeForThemeType(isWeb ? LIGHT : DARK); + themeData = ColorThemeData.createUnloadedThemeForThemeType(isWeb ? ColorScheme.LIGHT : ColorScheme.DARK); } themeData.setCustomizations(this.settings); this.applyTheme(themeData, undefined, true); @@ -217,14 +217,14 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { if (e.affectsConfiguration(ThemeSettings.DETECT_COLOR_SCHEME) || e.affectsConfiguration(ThemeSettings.DETECT_HC)) { this.handlePreferredSchemeUpdated(); } - if (e.affectsConfiguration(ThemeSettings.PREFERRED_DARK_THEME) && this.getPreferredColorScheme() === DARK) { - this.applyPreferredColorTheme(DARK); + if (e.affectsConfiguration(ThemeSettings.PREFERRED_DARK_THEME) && this.getPreferredColorScheme() === ColorScheme.DARK) { + this.applyPreferredColorTheme(ColorScheme.DARK); } - if (e.affectsConfiguration(ThemeSettings.PREFERRED_LIGHT_THEME) && this.getPreferredColorScheme() === LIGHT) { - this.applyPreferredColorTheme(LIGHT); + if (e.affectsConfiguration(ThemeSettings.PREFERRED_LIGHT_THEME) && this.getPreferredColorScheme() === ColorScheme.LIGHT) { + this.applyPreferredColorTheme(ColorScheme.LIGHT); } - if (e.affectsConfiguration(ThemeSettings.PREFERRED_HC_THEME) && this.getPreferredColorScheme() === HIGH_CONTRAST) { - this.applyPreferredColorTheme(HIGH_CONTRAST); + if (e.affectsConfiguration(ThemeSettings.PREFERRED_HC_THEME) && this.getPreferredColorScheme() === ColorScheme.HIGH_CONTRAST) { + this.applyPreferredColorTheme(ColorScheme.HIGH_CONTRAST); } if (e.affectsConfiguration(ThemeSettings.FILE_ICON_THEME)) { this.restoreFileIconTheme(); @@ -325,14 +325,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { // preferred scheme handling private installPreferredSchemeListener() { - window.matchMedia('(prefers-color-scheme: dark)').addListener(async () => this.handlePreferredSchemeUpdated()); - } - - public setOSHighContrast(highContrast: boolean): void { - if (this.isOSInHighContrast !== highContrast) { - this.isOSInHighContrast = highContrast; - this.handlePreferredSchemeUpdated(); - } + this.hostService.onDidChangeColorScheme(() => this.handlePreferredSchemeUpdated()); } private async handlePreferredSchemeUpdated() { @@ -357,23 +350,22 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { return undefined; } - private getPreferredColorScheme(): ThemeType | undefined { + private getPreferredColorScheme(): ColorScheme | undefined { const detectHCThemeSetting = this.configurationService.getValue(ThemeSettings.DETECT_HC); - if (this.isOSInHighContrast && detectHCThemeSetting) { - return HIGH_CONTRAST; + if (this.hostService.colorScheme === ColorScheme.HIGH_CONTRAST && detectHCThemeSetting) { + return ColorScheme.HIGH_CONTRAST; } if (this.configurationService.getValue(ThemeSettings.DETECT_COLOR_SCHEME)) { - if (window.matchMedia(`(prefers-color-scheme: light)`).matches) { - return LIGHT; - } else if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) { - return DARK; + const osScheme = this.hostService.colorScheme; + if (osScheme !== ColorScheme.HIGH_CONTRAST) { + return osScheme; } } return undefined; } - private async applyPreferredColorTheme(type: ThemeType): Promise { - const settingId = type === DARK ? ThemeSettings.PREFERRED_DARK_THEME : type === LIGHT ? ThemeSettings.PREFERRED_LIGHT_THEME : ThemeSettings.PREFERRED_HC_THEME; + private async applyPreferredColorTheme(type: ColorScheme): Promise { + const settingId = type === ColorScheme.DARK ? ThemeSettings.PREFERRED_DARK_THEME : type === ColorScheme.LIGHT ? ThemeSettings.PREFERRED_LIGHT_THEME : ThemeSettings.PREFERRED_HC_THEME; const themeSettingId = this.configurationService.getValue(settingId); if (themeSettingId) { const theme = await this.colorThemeRegistry.findThemeBySettingsId(themeSettingId, undefined); diff --git a/src/vs/workbench/services/themes/common/colorThemeData.ts b/src/vs/workbench/services/themes/common/colorThemeData.ts index b8c41191476..932b34cefbb 100644 --- a/src/vs/workbench/services/themes/common/colorThemeData.ts +++ b/src/vs/workbench/services/themes/common/colorThemeData.ts @@ -14,7 +14,7 @@ import * as objects from 'vs/base/common/objects'; import * as arrays from 'vs/base/common/arrays'; import * as resources from 'vs/base/common/resources'; import { Extensions as ColorRegistryExtensions, IColorRegistry, ColorIdentifier, editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry'; -import { ThemeType, ITokenStyle, getThemeTypeSelector } from 'vs/platform/theme/common/themeService'; +import { ITokenStyle, getThemeTypeSelector } from 'vs/platform/theme/common/themeService'; import { Registry } from 'vs/platform/registry/common/platform'; import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages'; import { URI } from 'vs/base/common/uri'; @@ -26,6 +26,7 @@ import { IExtensionResourceLoaderService } from 'vs/workbench/services/extension import { CharCode } from 'vs/base/common/charCode'; import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage'; import { ThemeConfiguration } from 'vs/workbench/services/themes/common/themeConfiguration'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; let colorRegistry = Registry.as(ColorRegistryExtensions.ColorContribution); @@ -540,17 +541,17 @@ export class ColorThemeData implements IWorkbenchColorTheme { return this.id.split(' ')[0]; } - get type(): ThemeType { + get type(): ColorScheme { switch (this.baseTheme) { - case VS_LIGHT_THEME: return 'light'; - case VS_HC_THEME: return 'hc'; - default: return 'dark'; + case VS_LIGHT_THEME: return ColorScheme.LIGHT; + case VS_HC_THEME: return ColorScheme.HIGH_CONTRAST; + default: return ColorScheme.DARK; } } // constructors - static createUnloadedThemeForThemeType(themeType: ThemeType, colorMap?: { [id: string]: string }): ColorThemeData { + static createUnloadedThemeForThemeType(themeType: ColorScheme, colorMap?: { [id: string]: string }): ColorThemeData { return ColorThemeData.createUnloadedTheme(getThemeTypeSelector(themeType), colorMap); } diff --git a/src/vs/workbench/services/themes/common/workbenchThemeService.ts b/src/vs/workbench/services/themes/common/workbenchThemeService.ts index cf14976f6fa..9186681075f 100644 --- a/src/vs/workbench/services/themes/common/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/common/workbenchThemeService.ts @@ -77,8 +77,6 @@ export interface IWorkbenchThemeService extends IThemeService { getProductIconTheme(): IWorkbenchProductIconTheme; getProductIconThemes(): Promise; onDidProductIconThemeChange: Event; - - setOSHighContrast(highContrast: boolean): void; } export interface IColorCustomizations { diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index a4de2b11a68..378c3b194e5 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -32,7 +32,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IInstantiationService, ServicesAccessor, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; -import { MenuBarVisibility, IWindowOpenable, IOpenWindowOptions, IOpenEmptyWindowOptions, ColorScheme } from 'vs/platform/windows/common/windows'; +import { MenuBarVisibility, IWindowOpenable, IOpenWindowOptions, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -114,6 +114,7 @@ import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFil import { newWriteableStream, ReadableStreamEvents } from 'vs/base/common/stream'; import { EncodingOracle, IEncodingOverride } from 'vs/workbench/services/textfile/browser/textFileService'; import { UTF16le, UTF16be, UTF8_with_bom } from 'vs/workbench/services/textfile/common/encoding'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export function createFileEditorInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined, undefined); @@ -1038,7 +1039,7 @@ export class TestHostService implements IHostService { async toggleFullScreen(): Promise { } - readonly colorScheme = ColorScheme.DEFAULT; + readonly colorScheme = ColorScheme.DARK; onDidChangeColorScheme = Event.None; } diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index c536d51d6f1..decfe69a8c8 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -25,7 +25,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, IOpenedWindow, ColorScheme } 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'; @@ -41,6 +41,7 @@ import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/ur import { MouseInputEvent } from 'vs/base/parts/sandbox/common/electronTypes'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IOSProperties } from 'vs/platform/electron/common/electron'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; export const TestWorkbenchConfiguration: INativeWorkbenchConfiguration = { windowId: 0, @@ -53,7 +54,7 @@ export const TestWorkbenchConfiguration: INativeWorkbenchConfiguration = { userEnv: {}, execPath: process.execPath, perfEntries: [], - colorScheme: ColorScheme.DEFAULT, + colorScheme: ColorScheme.DARK, ...parseArgs(process.argv, OPTIONS) }; diff --git a/src/vs/workbench/workbench.web.api.ts b/src/vs/workbench/workbench.web.api.ts index 008a5d9e46a..4fe99db6b18 100644 --- a/src/vs/workbench/workbench.web.api.ts +++ b/src/vs/workbench/workbench.web.api.ts @@ -147,12 +147,19 @@ interface IWindowIndicator { command?: string; } +enum ColorScheme { + DARK = 'dark', + LIGHT = 'light', + HIGH_CONTRAST = 'hc' +} + + interface IInitialColorTheme { /** * Initial color theme type. */ - themeType: 'light' | 'dark' | 'hc'; + themeType: ColorScheme; /** * A list of workbench colors to apply initially. From 39f8e2a1dc659ada453d0980e945b557e5bf817a Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 7 Sep 2020 17:38:06 +0200 Subject: [PATCH 33/98] #103454 do not use deprecated methods --- .../platform/extensionManagement/common/configRemotes.ts | 3 +-- src/vs/platform/userDataSync/common/keybindingsMerge.ts | 4 ++-- src/vs/platform/userDataSync/common/settingsMerge.ts | 4 ++-- src/vs/workbench/browser/parts/views/viewPaneContainer.ts | 7 +++---- .../contrib/extensions/common/extensionsUtils.ts | 3 +-- .../contrib/localizations/browser/localizationsActions.ts | 3 +-- .../contrib/preferences/browser/preferencesEditor.ts | 5 ++--- .../contrib/preferences/browser/preferencesRenderers.ts | 3 +-- .../configuration/common/configurationEditingService.ts | 3 +-- .../services/configuration/common/jsonEditingService.ts | 3 +-- .../workbench/services/views/common/viewContainerModel.ts | 8 ++++---- 11 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/configRemotes.ts b/src/vs/platform/extensionManagement/common/configRemotes.ts index b4d631be3f0..4db44fa4abf 100644 --- a/src/vs/platform/extensionManagement/common/configRemotes.ts +++ b/src/vs/platform/extensionManagement/common/configRemotes.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { endsWith } from 'vs/base/common/strings'; const SshProtocolMatcher = /^([^@:]+@)?([^:]+):/; const SshUrlMatcher = /^([^@:]+@)?([^:]+):(.+)$/; @@ -76,7 +75,7 @@ function stripPort(authority: string): string | null { function normalizeRemote(host: string | null, path: string, stripEndingDotGit: boolean): string | null { if (host && path) { - if (stripEndingDotGit && endsWith(path, '.git')) { + if (stripEndingDotGit && path.endsWith('.git')) { path = path.substr(0, path.length - 4); } return (path.indexOf('/') === 0) ? `${host}${path}` : `${host}/${path}`; diff --git a/src/vs/platform/userDataSync/common/keybindingsMerge.ts b/src/vs/platform/userDataSync/common/keybindingsMerge.ts index 3cbd0faf84d..de364130ad7 100644 --- a/src/vs/platform/userDataSync/common/keybindingsMerge.ts +++ b/src/vs/platform/userDataSync/common/keybindingsMerge.ts @@ -6,7 +6,7 @@ import * as objects from 'vs/base/common/objects'; import { parse } from 'vs/base/common/json'; import { IUserFriendlyKeybinding } from 'vs/platform/keybinding/common/keybinding'; -import { firstIndex as findFirstIndex, equals } from 'vs/base/common/arrays'; +import { equals } from 'vs/base/common/arrays'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import * as contentUtil from 'vs/platform/userDataSync/common/content'; import { IStringDictionary } from 'vs/base/common/collections'; @@ -346,7 +346,7 @@ function removeKeybindings(content: string, command: string, formattingOptions: function updateKeybindings(content: string, command: string, keybindings: IUserFriendlyKeybinding[], formattingOptions: FormattingOptions): string { const allKeybindings = parseKeybindings(content); - const location = findFirstIndex(allKeybindings, keybinding => keybinding.command === command || keybinding.command === `-${command}`); + const location = allKeybindings.findIndex(keybinding => keybinding.command === command || keybinding.command === `-${command}`); // Remove all entries with this command for (let index = allKeybindings.length - 1; index >= 0; index--) { if (allKeybindings[index].command === command || allKeybindings[index].command === `-${command}`) { diff --git a/src/vs/platform/userDataSync/common/settingsMerge.ts b/src/vs/platform/userDataSync/common/settingsMerge.ts index f4333ac84aa..99a411448ae 100644 --- a/src/vs/platform/userDataSync/common/settingsMerge.ts +++ b/src/vs/platform/userDataSync/common/settingsMerge.ts @@ -10,7 +10,7 @@ import { IStringDictionary } from 'vs/base/common/collections'; import { FormattingOptions, Edit, getEOL } from 'vs/base/common/jsonFormatter'; import * as contentUtil from 'vs/platform/userDataSync/common/content'; import { IConflictSetting, getDisallowedIgnoredSettings } from 'vs/platform/userDataSync/common/userDataSync'; -import { firstIndex, distinct } from 'vs/base/common/arrays'; +import { distinct } from 'vs/base/common/arrays'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export interface IMergeResult { @@ -320,7 +320,7 @@ interface InsertLocation { function getInsertLocation(key: string, sourceTree: INode[], targetTree: INode[]): InsertLocation { - const sourceNodeIndex = firstIndex(sourceTree, (node => node.setting?.key === key)); + const sourceNodeIndex = sourceTree.findIndex(node => node.setting?.key === key); const sourcePreviousNode: INode = sourceTree[sourceNodeIndex - 1]; if (sourcePreviousNode) { diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index d718c7846ca..4f683146121 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -11,7 +11,6 @@ import { attachStyler, IColorMapping, attachButtonStyler, attachLinkStyler, atta import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_BACKGROUND, SIDE_BAR_BACKGROUND, PANEL_SECTION_HEADER_FOREGROUND, PANEL_SECTION_HEADER_BACKGROUND, PANEL_SECTION_HEADER_BORDER, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_SECTION_BORDER } from 'vs/workbench/common/theme'; import { after, append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener, removeClass, addClass, createCSSRule, asCSSUrl, addClasses } from 'vs/base/browser/dom'; import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { firstIndex } from 'vs/base/common/arrays'; import { IAction, Separator, IActionViewItem } from 'vs/base/common/actions'; import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -1581,7 +1580,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } private removePane(pane: ViewPane): void { - const index = firstIndex(this.paneItems, i => i.pane === pane); + const index = this.paneItems.findIndex(i => i.pane === pane); if (index === -1) { return; @@ -1598,8 +1597,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } movePane(from: ViewPane, to: ViewPane): void { - const fromIndex = firstIndex(this.paneItems, item => item.pane === from); - const toIndex = firstIndex(this.paneItems, item => item.pane === to); + const fromIndex = this.paneItems.findIndex(item => item.pane === from); + const toIndex = this.paneItems.findIndex(item => item.pane === to); const fromViewDescriptor = this.viewContainerModel.visibleViewDescriptors[fromIndex]; const toViewDescriptor = this.viewContainerModel.visibleViewDescriptors[toIndex]; diff --git a/src/vs/workbench/contrib/extensions/common/extensionsUtils.ts b/src/vs/workbench/contrib/extensions/common/extensionsUtils.ts index f14ffc84eaf..9270ebca61f 100644 --- a/src/vs/workbench/contrib/extensions/common/extensionsUtils.ts +++ b/src/vs/workbench/contrib/extensions/common/extensionsUtils.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as arrays from 'vs/base/common/arrays'; import { localize } from 'vs/nls'; import { Event } from 'vs/base/common/event'; import { onUnexpectedError } from 'vs/base/common/errors'; @@ -44,7 +43,7 @@ export class KeymapExtensions extends Disposable implements IWorkbenchContributi private checkForOtherKeymaps(extensionIdentifier: IExtensionIdentifier): Promise { return this.instantiationService.invokeFunction(getInstalledExtensions).then(extensions => { const keymaps = extensions.filter(extension => isKeymapExtension(this.tipsService, extension)); - const extension = arrays.first(keymaps, extension => areSameExtensions(extension.identifier, extensionIdentifier)); + const extension = keymaps.find(extension => areSameExtensions(extension.identifier, extensionIdentifier)); if (extension && extension.globallyEnabled) { const otherKeymaps = keymaps.filter(extension => !areSameExtensions(extension.identifier, extensionIdentifier) && extension.globallyEnabled); if (otherKeymaps.length) { diff --git a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts index a935f264672..1304e665581 100644 --- a/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts +++ b/src/vs/workbench/contrib/localizations/browser/localizationsActions.ts @@ -12,7 +12,6 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { language } from 'vs/base/common/platform'; -import { firstIndex } from 'vs/base/common/arrays'; import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; @@ -47,7 +46,7 @@ export class ConfigureLocaleAction extends Action { public async run(): Promise { const languageOptions = await this.getLanguageOptions(); - const currentLanguageIndex = firstIndex(languageOptions, l => l.label === language); + const currentLanguageIndex = languageOptions.findIndex(l => l.label === language); try { const selectedLanguage = await this.quickInputService.pick(languageOptions, diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index e8bb2984293..efaef09f1f3 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -6,7 +6,6 @@ import * as DOM from 'vs/base/browser/dom'; import { Orientation, Sizing, SplitView } from 'vs/base/browser/ui/splitview/splitview'; import { Widget } from 'vs/base/browser/ui/widget'; -import * as arrays from 'vs/base/common/arrays'; import { Delayer, ThrottledDelayer } from 'vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { IStringDictionary } from 'vs/base/common/collections'; @@ -646,7 +645,7 @@ class PreferencesRenderersController extends Disposable { const current = this._settingsNavigator && this._settingsNavigator.current(); const navigatorSettings = this._lastQuery ? consolidatedSettings : []; const currentIndex = current ? - arrays.firstIndex(navigatorSettings, s => s.key === current.key) : + navigatorSettings.findIndex(s => s.key === current.key) : -1; this._settingsNavigator = new SettingsNavigator(navigatorSettings, Math.max(currentIndex, 0)); @@ -691,7 +690,7 @@ class PreferencesRenderersController extends Disposable { if (nlpMetadata) { const sortedKeys = Object.keys(nlpMetadata.scoredResults).sort((a, b) => nlpMetadata.scoredResults[b].score - nlpMetadata.scoredResults[a].score); const suffix = '##' + key; - data['nlpIndex'] = arrays.firstIndex(sortedKeys, key => key.endsWith(suffix)); + data['nlpIndex'] = sortedKeys.findIndex(key => key.endsWith(suffix)); } const settingLocation = this._findSetting(this.lastFilterResult, key); diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts index eb525604877..3829f930aad 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts @@ -31,7 +31,6 @@ import { DefaultSettingsEditorModel, SettingsEditorModel, WorkspaceConfiguration import { IMarkerService, IMarkerData, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; -import { find } from 'vs/base/common/arrays'; export interface IPreferencesRenderer extends IDisposable { readonly preferencesModel: IPreferencesEditorModel; @@ -321,7 +320,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR const { key, overrideOf } = setting; if (overrideOf) { const setting = this.getSetting(overrideOf); - return find(setting!.overrides!, override => override.key === key); + return setting!.overrides!.find(override => override.key === key); } const settingsGroups = this.filterResult ? this.filterResult.filteredGroups : this.preferencesModel.settingsGroups; return this.getPreference(key, settingsGroups); diff --git a/src/vs/workbench/services/configuration/common/configurationEditingService.ts b/src/vs/workbench/services/configuration/common/configurationEditingService.ts index d748536584c..ee38ee00689 100644 --- a/src/vs/workbench/services/configuration/common/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/common/configurationEditingService.ts @@ -7,7 +7,6 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import * as resources from 'vs/base/common/resources'; import * as json from 'vs/base/common/json'; -import * as strings from 'vs/base/common/strings'; import { setProperty } from 'vs/base/common/jsonEdit'; import { Queue } from 'vs/base/common/async'; import { Edit } from 'vs/base/common/jsonFormatter'; @@ -426,7 +425,7 @@ export class ConfigurationEditingService { // Without jsonPath, the entire configuration file is being replaced, so we just use JSON.stringify if (!jsonPath.length) { - const content = JSON.stringify(value, null, insertSpaces ? strings.repeat(' ', tabSize) : '\t'); + const content = JSON.stringify(value, null, insertSpaces ? ' '.repeat(tabSize) : '\t'); return [{ content, length: model.getValue().length, diff --git a/src/vs/workbench/services/configuration/common/jsonEditingService.ts b/src/vs/workbench/services/configuration/common/jsonEditingService.ts index 7aff6207f5b..a9686fae2d9 100644 --- a/src/vs/workbench/services/configuration/common/jsonEditingService.ts +++ b/src/vs/workbench/services/configuration/common/jsonEditingService.ts @@ -6,7 +6,6 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import * as json from 'vs/base/common/json'; -import * as strings from 'vs/base/common/strings'; import { setProperty } from 'vs/base/common/jsonEdit'; import { Queue } from 'vs/base/common/async'; import { Edit } from 'vs/base/common/jsonFormatter'; @@ -79,7 +78,7 @@ export class JSONEditingService implements IJSONEditingService { // With empty path the entire file is being replaced, so we just use JSON.stringify if (!path.length) { - const content = JSON.stringify(value, null, insertSpaces ? strings.repeat(' ', tabSize) : '\t'); + const content = JSON.stringify(value, null, insertSpaces ? ' '.repeat(tabSize) : '\t'); return [{ content, length: content.length, diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index a8e7d7ccee7..a360b073c53 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -12,7 +12,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; -import { firstIndex, move } from 'vs/base/common/arrays'; +import { move } from 'vs/base/common/arrays'; import { isUndefined, isUndefinedOrNull } from 'vs/base/common/types'; import { isEqual } from 'vs/base/common/resources'; @@ -442,8 +442,8 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode } move(from: string, to: string): void { - const fromIndex = firstIndex(this.viewDescriptorItems, v => v.viewDescriptor.id === from); - const toIndex = firstIndex(this.viewDescriptorItems, v => v.viewDescriptor.id === to); + const fromIndex = this.viewDescriptorItems.findIndex(v => v.viewDescriptor.id === from); + const toIndex = this.viewDescriptorItems.findIndex(v => v.viewDescriptor.id === to); const fromViewDescriptor = this.viewDescriptorItems[fromIndex]; const toViewDescriptor = this.viewDescriptorItems[toIndex]; @@ -531,7 +531,7 @@ export class ViewContainerModel extends Disposable implements IViewContainerMode this.contextKeys.delete(key); } } - const index = firstIndex(this.viewDescriptorItems, i => i.viewDescriptor.id === viewDescriptor.id); + const index = this.viewDescriptorItems.findIndex(i => i.viewDescriptor.id === viewDescriptor.id); if (index !== -1) { removed.push(viewDescriptor); const viewDescriptorItem = this.viewDescriptorItems[index]; From d69c272ce8520efd71efdbd48a1f4690d0c022d6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Sep 2020 17:50:49 +0200 Subject: [PATCH 34/98] environment - update jsdoc to clarify things --- .../environment/common/environmentService.ts | 14 ++++++++++++++ .../electron-sandbox/environmentService.ts | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/src/vs/workbench/services/environment/common/environmentService.ts b/src/vs/workbench/services/environment/common/environmentService.ts index 5d0d207d53e..01feb213573 100644 --- a/src/vs/workbench/services/environment/common/environmentService.ts +++ b/src/vs/workbench/services/environment/common/environmentService.ts @@ -11,8 +11,17 @@ import { URI } from 'vs/base/common/uri'; export const IWorkbenchEnvironmentService = createDecorator('environmentService'); +/** + * A workbench specific environment service that is only present in workbench + * layer. + */ export interface IWorkbenchEnvironmentService extends IEnvironmentService { + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // NOTE: KEEP THIS INTERFACE AS SMALL AS POSSIBLE. AS SUCH: + // - PUT NON-WEB PROPERTIES INTO NATIVE WB ENV SERVICE + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + readonly _serviceBrand: undefined; readonly configuration: IWindowConfiguration; @@ -30,4 +39,9 @@ export interface IWorkbenchEnvironmentService extends IEnvironmentService { readonly webviewCspSource: string; readonly skipReleaseNotes: boolean; + + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // NOTE: KEEP THIS INTERFACE AS SMALL AS POSSIBLE. AS SUCH: + // - PUT NON-WEB PROPERTIES INTO NATIVE WB ENV SERVICE + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } diff --git a/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts b/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts index 59e0cb235a5..b75dd5fdd9e 100644 --- a/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts +++ b/src/vs/workbench/services/environment/electron-sandbox/environmentService.ts @@ -10,6 +10,10 @@ import { URI } from 'vs/base/common/uri'; export interface INativeWorkbenchConfiguration extends IWindowConfiguration, INativeWindowConfiguration { } +/** + * A subclass of the `IWorkbenchEnvironmentService` to be used only in native + * environments (Windows, Linux, macOS) but not e.g. web. + */ export interface INativeWorkbenchEnvironmentService extends IWorkbenchEnvironmentService, INativeEnvironmentService { readonly configuration: INativeWorkbenchConfiguration; From 718ec3230365255fedc7d7fe3bb920bcfc60fcf0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 7 Sep 2020 18:26:12 +0200 Subject: [PATCH 35/98] keyboard - rename and cleanup some editor related contextkeys --- src/vs/workbench/browser/contextkeys.ts | 12 +++++------ .../parts/editor/editor.contribution.ts | 4 ++-- .../browser/parts/editor/editorGroupView.ts | 12 +++++------ src/vs/workbench/common/editor.ts | 21 ++++++++++++------- .../files/browser/fileActions.contribution.ts | 4 ++-- .../contrib/remote/browser/remoteIndicator.ts | 5 ++--- .../electron-browser/remote.contribution.ts | 3 +-- .../electron-sandbox/desktop.contribution.ts | 4 ++-- .../dialogs/browser/simpleFileDialog.ts | 5 +++-- 9 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 1de01f036f3..cd77e992cdc 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys'; -import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorIsReadonlyContext, EditorAreaVisibleContext, DirtyWorkingCopiesContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor'; +import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, EditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor'; import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom'; import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -21,14 +21,12 @@ import { PanelPositionContext } from 'vs/workbench/common/panel'; import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; -export const RemoteNameContext = new RawContextKey('remoteName', ''); -export const RemoteConnectionState = new RawContextKey<'' | 'initializing' | 'disconnected' | 'connected'>('remoteConnectionState', ''); - export const WorkbenchStateContext = new RawContextKey('workbenchState', undefined); - export const WorkspaceFolderCountContext = new RawContextKey('workspaceFolderCount', 0); -export const RemoteFileDialogContext = new RawContextKey('remoteFileDialogVisible', false); +export const DirtyWorkingCopiesContext = new RawContextKey('dirtyWorkingCopies', false); + +export const RemoteNameContext = new RawContextKey('remoteName', ''); export const IsFullscreenContext = new RawContextKey('isFullscreen', false); @@ -89,7 +87,7 @@ export class WorkbenchContextKeysHandler extends Disposable { // Editors this.activeEditorContext = ActiveEditorContext.bindTo(this.contextKeyService); - this.activeEditorIsReadonly = ActiveEditorIsReadonlyContext.bindTo(this.contextKeyService); + this.activeEditorIsReadonly = EditorReadonlyContext.bindTo(this.contextKeyService); this.activeEditorAvailableEditorIds = ActiveEditorAvailableEditorIdsContext.bindTo(this.contextKeyService); this.editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService); this.textCompareEditorVisibleContext = TextCompareEditorVisibleContext.bindTo(this.contextKeyService); diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index a03f87b0bd5..3473bb05dee 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -525,7 +525,7 @@ appendEditorToolItem( title: nls.localize('close', "Close"), icon: { id: 'codicon/close' } }, - ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.not('groupActiveEditorDirty')), + ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.not('activeEditorIsDirty')), 1000000, // towards the far end { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, @@ -540,7 +540,7 @@ appendEditorToolItem( title: nls.localize('close', "Close"), icon: { id: 'codicon/close-dirty' } }, - ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.has('groupActiveEditorDirty')), + ContextKeyExpr.and(ContextKeyExpr.not('config.workbench.editor.showTabs'), ContextKeyExpr.has('activeEditorIsDirty')), 1000000, // towards the far end { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 0fcb9999b13..900ee82ecc6 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup'; -import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, EditorStickyContext, EditorPinnedContext } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, EditorStickyContext, EditorPinnedContext } from 'vs/workbench/common/editor'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom'; @@ -217,10 +217,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } private handleGroupContextKeys(contextKeyService: IContextKeyService): void { - const groupActiveEditorDirtyContextKey = EditorGroupActiveEditorDirtyContext.bindTo(contextKeyService); - const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(contextKeyService); + const groupActiveEditorDirtyContext = EditorDirtyContext.bindTo(contextKeyService); const groupActiveEditorPinnedContext = EditorPinnedContext.bindTo(contextKeyService); const groupActiveEditorStickyContext = EditorStickyContext.bindTo(contextKeyService); + const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(contextKeyService); const activeEditorListener = new MutableDisposable(); @@ -229,10 +229,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView { const activeEditor = this._group.activeEditor; if (activeEditor) { - groupActiveEditorDirtyContextKey.set(activeEditor.isDirty() && !activeEditor.isSaving()); - activeEditorListener.value = activeEditor.onDidChangeDirty(() => groupActiveEditorDirtyContextKey.set(activeEditor.isDirty() && !activeEditor.isSaving())); + groupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving()); + activeEditorListener.value = activeEditor.onDidChangeDirty(() => groupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving())); } else { - groupActiveEditorDirtyContextKey.set(false); + groupActiveEditorDirtyContext.set(false); } }; diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 84f8ce721ad..7459f051f22 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -24,23 +24,28 @@ import { IResourceEditorInputType } from 'vs/workbench/services/editor/common/ed import { IRange } from 'vs/editor/common/core/range'; import { IExtUri } from 'vs/base/common/resources'; -export const DirtyWorkingCopiesContext = new RawContextKey('dirtyWorkingCopies', false); +// Editor State Context Keys +export const EditorDirtyContext = new RawContextKey('activeEditorIsDirty', false); +export const EditorPinnedContext = new RawContextKey('activeEditorIsNotPreview', false); +export const EditorStickyContext = new RawContextKey('activeEditorIsPinned', false); +export const EditorReadonlyContext = new RawContextKey('activeEditorIsReadonly', false); + +// Editor Kind Context Keys export const ActiveEditorContext = new RawContextKey('activeEditor', null); -export const ActiveEditorIsReadonlyContext = new RawContextKey('activeEditorIsReadonly', false); export const ActiveEditorAvailableEditorIdsContext = new RawContextKey('activeEditorAvailableEditorIds', ''); -export const EditorsVisibleContext = new RawContextKey('editorIsOpen', false); -export const EditorPinnedContext = new RawContextKey('editorPinned', false); -export const EditorStickyContext = new RawContextKey('editorSticky', false); -export const EditorGroupActiveEditorDirtyContext = new RawContextKey('groupActiveEditorDirty', false); -export const EditorGroupEditorsCountContext = new RawContextKey('groupEditorsCount', 0); -export const NoEditorsVisibleContext = EditorsVisibleContext.toNegated(); export const TextCompareEditorVisibleContext = new RawContextKey('textCompareEditorVisible', false); export const TextCompareEditorActiveContext = new RawContextKey('textCompareEditorActive', false); + +// Editor Group Context Keys +export const EditorGroupEditorsCountContext = new RawContextKey('groupEditorsCount', 0); export const ActiveEditorGroupEmptyContext = new RawContextKey('activeEditorGroupEmpty', false); export const ActiveEditorGroupIndexContext = new RawContextKey('activeEditorGroupIndex', 0); export const ActiveEditorGroupLastContext = new RawContextKey('activeEditorGroupLast', false); export const MultipleEditorGroupsContext = new RawContextKey('multipleEditorGroups', false); export const SingleEditorGroupsContext = MultipleEditorGroupsContext.toNegated(); + +// Editor Layout Context Keys +export const EditorsVisibleContext = new RawContextKey('editorIsOpen', false); export const InEditorZenModeContext = new RawContextKey('inZenMode', false); export const IsCenteredLayoutContext = new RawContextKey('isCenteredLayout', false); export const SplitEditorsVertically = new RawContextKey('splitEditorsVertically', false); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index ac1df7b3a5c..d24581d9416 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -22,11 +22,11 @@ import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfi import { ResourceContextKey } from 'vs/workbench/common/resources'; import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService'; import { Schemas } from 'vs/base/common/network'; -import { WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys'; +import { DirtyWorkingCopiesContext, WorkspaceFolderCountContext } from 'vs/workbench/browser/contextkeys'; import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { OpenFileFolderAction, OpenFileAction, OpenFolderAction, OpenWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions'; -import { DirtyWorkingCopiesContext, ActiveEditorContext } from 'vs/workbench/common/editor'; +import { ActiveEditorContext } from 'vs/workbench/common/editor'; import { SidebarFocusContext } from 'vs/workbench/common/viewlet'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index fb51919e9b1..c6dfe890b38 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -12,7 +12,7 @@ import { MenuId, IMenuService, MenuItemAction, IMenu, MenuRegistry, registerActi import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar'; import { ILabelService } from 'vs/platform/label/common/label'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -21,7 +21,6 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/ import { PersistentConnectionEventType } from 'vs/platform/remote/common/remoteAgentConnection'; import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { RemoteConnectionState } from 'vs/workbench/browser/contextkeys'; import { isWeb } from 'vs/base/common/platform'; import { once } from 'vs/base/common/functional'; @@ -38,7 +37,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr private remoteAuthority = this.environmentService.configuration.remoteAuthority; private connectionState: 'initializing' | 'connected' | 'disconnected' | undefined = undefined; - private connectionStateContextKey = RemoteConnectionState.bindTo(this.contextKeyService); + private connectionStateContextKey = new RawContextKey<'' | 'initializing' | 'disconnected' | 'connected'>('remoteConnectionState', '').bindTo(this.contextKeyService); constructor( @IStatusbarService private readonly statusbarService: IStatusbarService, 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 365ae95ec0e..52c5305bc26 100644 --- a/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts +++ b/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts @@ -27,9 +27,8 @@ import { PersistentConnectionEventType } from 'vs/platform/remote/common/remoteA import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver'; -import { RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys'; import { IDownloadService } from 'vs/platform/download/common/download'; -import { OpenLocalFileFolderCommand, OpenLocalFileCommand, OpenLocalFolderCommand, SaveLocalFileCommand } from 'vs/workbench/services/dialogs/browser/simpleFileDialog'; +import { OpenLocalFileFolderCommand, OpenLocalFileCommand, OpenLocalFolderCommand, SaveLocalFileCommand, RemoteFileDialogContext } from 'vs/workbench/services/dialogs/browser/simpleFileDialog'; class RemoteChannelsContribution implements IWorkbenchContribution { diff --git a/src/vs/workbench/electron-sandbox/desktop.contribution.ts b/src/vs/workbench/electron-sandbox/desktop.contribution.ts index 07fe262c796..416529f9650 100644 --- a/src/vs/workbench/electron-sandbox/desktop.contribution.ts +++ b/src/vs/workbench/electron-sandbox/desktop.contribution.ts @@ -17,7 +17,7 @@ import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/co 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 { EditorsVisibleContext, SingleEditorGroupsContext } from 'vs/workbench/common/editor'; 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'; @@ -45,7 +45,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; KeybindingsRegistry.registerCommandAndKeybindingRule({ id: CloseCurrentWindowAction.ID, // close the window when the last editor is closed by reusing the same keybinding weight: KeybindingWeight.WorkbenchContrib, - when: ContextKeyExpr.and(NoEditorsVisibleContext, SingleEditorGroupsContext), + when: ContextKeyExpr.and(EditorsVisibleContext.toNegated(), SingleEditorGroupsContext), primary: KeyMod.CtrlCmd | KeyCode.KEY_W, handler: accessor => { const electronService = accessor.get(IElectronService); diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index 46801bd7349..cbefdbce353 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -21,12 +21,11 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses'; import { Schemas } from 'vs/base/common/network'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { equalsIgnoreCase, format, startsWithIgnoreCase } from 'vs/base/common/strings'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment'; import { isValidBasename } from 'vs/base/common/extpath'; -import { RemoteFileDialogContext } from 'vs/workbench/browser/contextkeys'; import { Emitter } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createCancelablePromise, CancelablePromise } from 'vs/base/common/async'; @@ -98,6 +97,8 @@ enum UpdateResult { InvalidPath } +export const RemoteFileDialogContext = new RawContextKey('remoteFileDialogVisible', false); + export class SimpleFileDialog { private options!: IOpenDialogOptions; private currentFolder!: URI; From 1d7b32b88049db0c3f05df8a3557f94ec0c51fc1 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 7 Sep 2020 13:25:24 -0700 Subject: [PATCH 36/98] chore: bump electron@9.3.0 --- .yarnrc | 2 +- cgmanifest.json | 4 ++-- package.json | 2 +- yarn.lock | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.yarnrc b/.yarnrc index 3c6eccfb102..fbf612d0989 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "9.2.1" +target "9.3.0" runtime "electron" diff --git a/cgmanifest.json b/cgmanifest.json index e6e8ce8a5c1..859af568b1b 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "03c7a54dc534ce1867d4393b9b1a6989d4a7e005" + "commitHash": "fb03807cd21915ddc3aa2521ba4f5ba14597bd7e" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "9.2.1" + "version": "9.3.0" }, { "component": { diff --git a/package.json b/package.json index 09d7e57699e..554b31a01e8 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "9.2.1", + "electron": "9.3.0", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "event-stream": "3.3.4", diff --git a/yarn.lock b/yarn.lock index b3a08230717..c00f67c5de6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2749,10 +2749,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@9.2.1: - version "9.2.1" - resolved "https://registry.yarnpkg.com/electron/-/electron-9.2.1.tgz#54ef574e1af4ae967b5efa94312f1b6458d44a02" - integrity sha512-ZsetaQjXB8+9/EFW1FnfK4ukpkwXCxMEaiKiUZhZ0ZLFlLnFCpe0Bg4vdDf7e4boWGcnlgN1jAJpBw7w0eXuqA== +electron@9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-9.3.0.tgz#a4f3dc17f31acc6797eb4c2c4bd0d0e25efb939b" + integrity sha512-7zPLEZ+kOjVJqfawMQ0vVuZZRqvZIeiID3tbjjbVybbxXIlFMpZ2jogoh7PV3rLrtm+dKRfu7Qc4E7ob1d0FqQ== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" From 0e91435a07bace3d997417c9e9e7a0339de29870 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 09:31:04 +0200 Subject: [PATCH 37/98] chore - trusted types search --- .vscode/searches/TrustedTypes.code-search | 493 ++++++++++++++++++++++ 1 file changed, 493 insertions(+) create mode 100644 .vscode/searches/TrustedTypes.code-search diff --git a/.vscode/searches/TrustedTypes.code-search b/.vscode/searches/TrustedTypes.code-search new file mode 100644 index 00000000000..f4ded269d55 --- /dev/null +++ b/.vscode/searches/TrustedTypes.code-search @@ -0,0 +1,493 @@ +# Query: .innerHTML = +# Flags: CaseSensitive WordMatch +# Including: src/vs/**/*.{t,j}s +# Excluding: *.test.ts +# ContextLines: 3 + +59 results - 40 files + +src/vs/base/browser/markdownRenderer.ts: + 156 const strValue = values[0]; + 157 const span = element.querySelector(`div[data-code="${id}"]`); + 158 if (span) { + 159: span.innerHTML = strValue; + 160 } + 161 }).catch(err => { + 162 // ignore + + 238 return true; + 239 } + 240 + 241: element.innerHTML = insane(renderedMarkdown, { + 242 allowedSchemes, + 243 // allowedTags should included everything that markdown renders to. + 244 // Since we have our own sanitize function for marked, it's possible we missed some tag so let insane make sure. + +src/vs/base/browser/ui/codicons/codiconStyles.ts: + 20 for (let c of iconRegistry.all) { + 21 rules.push(formatRule(c)); + 22 } + 23: codiconStyleSheet.innerHTML = rules.join('\n'); + 24 } + 25 + 26 const delayer = new RunOnceScheduler(updateAll, 0); + +src/vs/base/browser/ui/contextview/contextview.ts: + 157 this.shadowRootHostElement = DOM.$('.shadow-root-host'); + 158 this.container.appendChild(this.shadowRootHostElement); + 159 this.shadowRoot = this.shadowRootHostElement.attachShadow({ mode: 'open' }); + 160: this.shadowRoot.innerHTML = ` + 161 + +src/vs/base/browser/ui/list/listWidget.ts: + 826 + 827 const newStyles = content.join('\n'); + 828 if (newStyles !== this.styleElement.innerHTML) { + 829: this.styleElement.innerHTML = newStyles; + 830 } + 831 } + 832 } + +src/vs/base/browser/ui/menu/menu.ts: + 229 private initializeStyleSheet(container: HTMLElement): void { + 230 if (isInShadowDOM(container)) { + 231 this.styleSheet = createStyleSheet(container); + 232: this.styleSheet.innerHTML = MENU_WIDGET_CSS; + 233 } else { + 234 if (!Menu.globalStyleSheet) { + 235 Menu.globalStyleSheet = createStyleSheet(); + 236: Menu.globalStyleSheet.innerHTML = MENU_WIDGET_CSS; + 237 } + 238 + 239 this.styleSheet = Menu.globalStyleSheet; + +src/vs/base/browser/ui/menu/menubar.ts: + 548 } + 549 + 550 innerHtml = innerHtml.replace(/&&/g, '&'); + 551: titleElement.innerHTML = innerHtml; + 552 } else { + 553: titleElement.innerHTML = cleanMenuLabel.replace(/&&/g, '&'); + 554 } + 555 + 556 let mnemonicMatches = MENU_MNEMONIC_REGEX.exec(label); + +src/vs/base/browser/ui/sash/sash.ts: + 266 } + 267 } + 268 + 269: style.innerHTML = `* { cursor: ${cursor} !important; }`; + 270 }; + 271 + 272 const disposables = new DisposableStore(); + +src/vs/base/browser/ui/selectBox/selectBoxCustom.ts: + 367 content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { outline: none !important; }`); + 368 } + 369 + 370: this.styleElement.innerHTML = content.join('\n'); + 371 + 372 this.applyStyles(); + 373 } + + 705 }); + 706 + 707 + 708: container.innerHTML = this.options[longest].text + (!!this.options[longest].decoratorRight ? (this.options[longest].decoratorRight + ' ') : ''); + 709 elementWidth = dom.getTotalWidth(container); + 710 } + 711 + +src/vs/base/browser/ui/tree/abstractTree.ts: + 1476 + 1477 const newStyles = content.join('\n'); + 1478 if (newStyles !== this.styleElement.innerHTML) { + 1479: this.styleElement.innerHTML = newStyles; + 1480 } + 1481 + 1482 this.view.style(styles); + +src/vs/base/parts/quickinput/browser/quickInput.ts: + 1693 } + 1694 const newStyles = content.join('\n'); + 1695 if (newStyles !== this.ui.styleSheet.innerHTML) { + 1696: this.ui.styleSheet.innerHTML = newStyles; + 1697 } + 1698 } + 1699 } + +src/vs/code/electron-browser/workbench/workbench.js: + 124 const style = document.createElement('style'); + 125 style.className = 'initialShellColors'; + 126 document.head.appendChild(style); + 127: style.innerHTML = `body { background-color: ${shellBackground}; color: ${shellForeground}; margin: 0; padding: 0; }`; + 128 + 129 if (data && data.layoutInfo) { + 130 // restore parts if possible (we might not always store layout info) + + 150 + 151 if (configuration.folderUri || configuration.workspace) { + 152 // folder or workspace -> status bar color, sidebar + 153: splash.innerHTML = ` + 154
+ 155
+ 156
+ + 158 `; + 159 } else { + 160 // empty -> speical status bar color, no sidebar + 161: splash.innerHTML = ` + 162
+ 163
+ 164
+ +src/vs/code/electron-sandbox/issue/issueReporterMain.ts: + 57 const platformClass = platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac'; + 58 addClass(document.body, platformClass); // used by our fonts + 59 + 60: document.body.innerHTML = BaseHtml(); + 61 const issueReporter = new IssueReporter(configuration); + 62 issueReporter.render(); + 63 document.body.style.display = 'block'; + + 244 content.push(`.monaco-text-button:not(.disabled):hover, .monaco-text-button:focus { background-color: ${styles.buttonHoverBackground} !important; }`); + 245 } + 246 + 247: styleTag.innerHTML = content.join('\n'); + 248 document.head.appendChild(styleTag); + 249 document.body.style.color = styles.color || ''; + 250 } + +src/vs/code/electron-sandbox/processExplorer/processExplorerMain.ts: + 282 this.listeners.clear(); + 283 + 284 const tableHead = document.createElement('thead'); + 285: tableHead.innerHTML = ` + 286 ${localize('cpu', "CPU %")} + 287 ${localize('memory', "Memory (MB)")} + 288 ${localize('pid', "PID")} + + 319 content.push(`.highest { color: ${styles.highlightForeground}; }`); + 320 } + 321 + 322: styleTag.innerHTML = content.join('\n'); + 323 if (document.head) { + 324 document.head.appendChild(styleTag); + 325 } + +src/vs/editor/browser/view/domLineBreaksComputer.ts: + 107 allCharOffsets[i] = tmp[0]; + 108 allVisibleColumns[i] = tmp[1]; + 109 } + 110: containerDomNode.innerHTML = sb.build(); + 111 + 112 containerDomNode.style.position = 'absolute'; + 113 containerDomNode.style.top = '10000'; + +src/vs/editor/browser/view/viewLayer.ts: + 507 private _finishRenderingNewLines(ctx: IRendererContext, domNodeIsEmpty: boolean, newLinesHTML: string, wasNew: boolean[]): void { + 508 const lastChild = this.domNode.lastChild; + 509 if (domNodeIsEmpty || !lastChild) { + 510: this.domNode.innerHTML = newLinesHTML; + 511 } else { + 512 lastChild.insertAdjacentHTML('afterend', newLinesHTML); + 513 } + + 525 private _finishRenderingInvalidLines(ctx: IRendererContext, invalidLinesHTML: string, wasInvalid: boolean[]): void { + 526 const hugeDomNode = document.createElement('div'); + 527 + 528: hugeDomNode.innerHTML = invalidLinesHTML; + 529 + 530 for (let i = 0; i < ctx.linesLength; i++) { + 531 const line = ctx.lines[i]; + +src/vs/editor/browser/widget/diffEditorWidget.ts: + 2157 + 2158 let domNode = document.createElement('div'); + 2159 domNode.className = `view-lines line-delete ${MOUSE_CURSOR_TEXT_CSS_CLASS_NAME}`; + 2160: domNode.innerHTML = sb.build(); + 2161 Configuration.applyFontInfoSlow(domNode, fontInfo); + 2162 + 2163 let marginDomNode = document.createElement('div'); + 2164 marginDomNode.className = 'inline-deleted-margin-view-zone'; + 2165: marginDomNode.innerHTML = marginHTML.join(''); + 2166 Configuration.applyFontInfoSlow(marginDomNode, fontInfo); + 2167 + 2168 return { + +src/vs/editor/standalone/browser/colorizer.ts: + 40 let text = domNode.firstChild ? domNode.firstChild.nodeValue : ''; + 41 domNode.className += ' ' + theme; + 42 let render = (str: string) => { + 43: domNode.innerHTML = str; + 44 }; + 45 return this.colorize(modeService, text || '', mimeType, options).then(render, (err) => console.error(err)); + 46 } + +src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts: + 211 if (!this._globalStyleElement) { + 212 this._globalStyleElement = dom.createStyleSheet(); + 213 this._globalStyleElement.className = 'monaco-colors'; + 214: this._globalStyleElement.innerHTML = this._css; + 215 this._styleElements.push(this._globalStyleElement); + 216 } + 217 return Disposable.None; + + 220 private _registerShadowDomContainer(domNode: HTMLElement): IDisposable { + 221 const styleElement = dom.createStyleSheet(domNode); + 222 styleElement.className = 'monaco-colors'; + 223: styleElement.innerHTML = this._css; + 224 this._styleElements.push(styleElement); + 225 return { + 226 dispose: () => { + + 290 ruleCollector.addRule(generateTokensCSSForColorMap(colorMap)); + 291 + 292 this._css = cssRules.join('\n'); + 293: this._styleElements.forEach(styleElement => styleElement.innerHTML = this._css); + 294 + 295 TokenizationRegistry.setColorMap(colorMap); + 296 this._onColorThemeChange.fire(theme); + +src/vs/editor/test/browser/controller/imeTester.ts: + 55 let content = this._model.getModelLineContent(i); + 56 r += content + '
'; + 57 } + 58: output.innerHTML = r; + 59 } + 60 } + 61 + + 69 let title = document.createElement('div'); + 70 title.className = 'title'; + 71 + 72: title.innerHTML = description + '. Type ' + inputStr + ''; + 73 container.appendChild(title); + 74 + 75 let startBtn = document.createElement('button'); + +src/vs/workbench/browser/parts/compositePart.ts: + 414 const $this = this; + 415 return { + 416 updateTitle: (id, title, keybinding) => { + 417: titleLabel.innerHTML = strings.escape(title); + 418 titleLabel.title = keybinding ? nls.localize('titleTooltip', "{0} ({1})", title, keybinding) : title; + 419 }, + 420 + +src/vs/workbench/browser/parts/statusbar/statusbarPart.ts: + 672 this.styleElement = createStyleSheet(container); + 673 } + 674 + 675: this.styleElement.innerHTML = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`; + 676 } + 677 + 678 private doCreateStatusItem(id: string, alignment: StatusbarAlignment, ...extraClasses: string[]): HTMLElement { + +src/vs/workbench/contrib/comments/browser/commentsView.ts: + 109 content.push(`.comments-panel .comments-panel-container .text code { color: ${codeTextForegroundColor}; }`); + 110 } + 111 + 112: styleElement.innerHTML = content.join('\n'); + 113 } + 114 + 115 private async renderComments(): Promise { + +src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts: + 692 } + 693 + 694 if (label) { + 695: this._headingLabel.innerHTML = strings.escape(label); + 696 this._headingLabel.setAttribute('aria-label', label); + 697 } + 698 } + + 916 font-weight: ${fontInfo.fontWeight}; + 917 }`); + 918 + 919: this._styleElement.innerHTML = content.join('\n'); + 920 + 921 // Editor decorations should also be responsive to theme changes + 922 this.setCommentEditorDecorations(); + +src/vs/workbench/contrib/debug/browser/repl.ts: + 306 const replInputLineHeight = this.replInput.getOption(EditorOption.lineHeight); + 307 + 308 // Set the font size, font family, line height and align the twistie to be centered, and input theme color + 309: this.styleElement.innerHTML = ` + 310 .repl .repl-tree .expression { + 311 font-size: ${fontSize}px; + 312 font-family: ${fontFamily}; + +src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts: + 84 this.styleElement = createStyleSheet(container); + 85 } + 86 + 87: this.styleElement.innerHTML = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor} !important; }`; + 88 } + 89 + 90 private getColorKey(noFolderColor: string, debuggingColor: string, normalColor: string): string { + +src/vs/workbench/contrib/files/browser/views/explorerView.ts: + 812 + 813 const newStyles = content.join('\n'); + 814 if (newStyles !== this.styleElement.innerHTML) { + 815: this.styleElement.innerHTML = newStyles; + 816 } + 817 } + 818 + +src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffList.ts: + 222 + 223 const newStyles = content.join('\n'); + 224 if (newStyles !== this.styleElement.innerHTML) { + 225: this.styleElement.innerHTML = newStyles; + 226 } + 227 } + 228 } + +src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts: + 1033 + 1034 const newStyles = content.join('\n'); + 1035 if (newStyles !== this.styleElement.innerHTML) { + 1036: this.styleElement.innerHTML = newStyles; + 1037 } + 1038 } + 1039 + +src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts: + 443 + 444 private getMarkdownDragImage(templateData: MarkdownCellRenderTemplate): HTMLElement { + 445 const dragImageContainer = DOM.$('.cell-drag-image.monaco-list-row.focused.markdown-cell-row'); + 446: dragImageContainer.innerHTML = templateData.container.outerHTML; + 447 + 448 // Remove all rendered content nodes after the + 449 const markdownContent = dragImageContainer.querySelector('.cell.markdown')!; + + 587 + 588 private getDragImageImpl(templateData: BaseCellRenderTemplate, editor: ICodeEditor, type: 'code' | 'markdown'): HTMLElement | null { + 589 const dragImageContainer = DOM.$(`.cell-drag-image.monaco-list-row.focused.${type}-cell-row`); + 590: dragImageContainer.innerHTML = templateData.container.innerHTML; + 591 + 592 const editorContainer = dragImageContainer.querySelector('.cell-editor-container'); + 593 if (!editorContainer) { + + 599 return null; + 600 } + 601 + 602: editorContainer.innerHTML = richEditorText; + 603 + 604 return dragImageContainer; + 605 } + +src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts: + 77 return; + 78 } + 79 + 80: this.leftContributedItemsContainer.innerHTML = ''; + 81: this.rightContributedItemsContainer.innerHTML = ''; + 82 this.itemsDisposable.clear(); + 83 + 84 const items = this.notebookCellStatusBarService.getEntries(this.currentContext.cell.uri); + +src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts: + 375 addMouseoverListeners(outputNode, outputId); + 376 const content = data.content; + 377 if (content.type === RenderOutputType.Html) { + 378: outputNode.innerHTML = content.htmlContent; + 379 cellOutputContainer.appendChild(outputNode); + 380 domEval(outputNode); + 381 } else { + +src/vs/workbench/contrib/sash/browser/sash.ts: + 35 const size = clamp(this.configurationService.getValue(this.configurationName) ?? minSize, minSize, maxSize); + 36 + 37 // Update styles + 38: this.stylesheet.innerHTML = ` + 39 .monaco-sash.vertical { cursor: ew-resize; top: 0; width: ${size}px; height: 100%; } + 40 .monaco-sash.horizontal { cursor: ns-resize; left: 0; width: 100%; height: ${size}px; } + 41 .monaco-sash:not(.disabled).orthogonal-start::before, .monaco-sash:not(.disabled).orthogonal-end::after { content: ' '; height: ${size * 2}px; width: ${size * 2}px; z-index: 100; display: block; cursor: all-scroll; position: absolute; } + +src/vs/workbench/contrib/scm/browser/dirtydiffDecorator.ts: + 1301 + 1302 private setViewState(state: IViewState): void { + 1303 this.viewState = state; + 1304: this.stylesheet.innerHTML = ` + 1305 .monaco-editor .dirty-diff-modified,.monaco-editor .dirty-diff-added{border-left-width:${state.width}px;} + 1306 .monaco-editor .dirty-diff-modified, .monaco-editor .dirty-diff-added, .monaco-editor .dirty-diff-deleted { + 1307 opacity: ${state.visibility === 'always' ? 1 : 0}; + +src/vs/workbench/contrib/watermark/browser/watermark.ts: + 141 const dd = dom.append(dl, $('dd')); + 142 const keybinding = new KeybindingLabel(dd, OS, { renderUnboundKeybindings: true }); + 143 keybinding.set(this.keybindingService.lookupKeybinding(entry.id)); + 144: dd.innerHTML = keybinding.element.outerHTML; + 145 }); + 146 }; + 147 + +src/vs/workbench/contrib/webview/browser/webviewIconManager.ts: + 61 } + 62 } + 63 } + 64: this._styleElement.innerHTML = cssRules.join('\n'); + 65 } + 66 } + +src/vs/workbench/contrib/webview/browser/pre/main.js: + 386 // apply default styles + 387 const defaultStyles = newDocument.createElement('style'); + 388 defaultStyles.id = '_defaultStyles'; + 389: defaultStyles.innerHTML = defaultCssRules; + 390 newDocument.head.prepend(defaultStyles); + 391 + 392 applyStyles(newDocument, newDocument.body); + +src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts: + 328 + 329 const prodName = container.querySelector('.welcomePage .title .caption') as HTMLElement; + 330 if (prodName) { + 331: prodName.innerHTML = this.productService.nameLong; + 332 } + 333 + 334 recentlyOpened.then(({ workspaces }) => { + +src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts: + 281 + 282 const content = model.main.textEditorModel.getValue(EndOfLinePreference.LF); + 283 if (!strings.endsWith(input.resource.path, '.md')) { + 284: this.content.innerHTML = content; + 285 this.updateSizeClasses(); + 286 this.decorateContent(); + 287 this.contentDisposables.push(this.keybindingService.onDidUpdateKeybindings(() => this.decorateContent())); + + 303 const innerContent = document.createElement('div'); + 304 innerContent.classList.add('walkThroughContent'); // only for markdown files + 305 const markdown = this.expandMacros(content); + 306: innerContent.innerHTML = marked(markdown, { renderer }); + 307 this.content.appendChild(innerContent); + 308 + 309 model.snippets.forEach((snippet, i) => { + +src/vs/workbench/services/textMate/browser/abstractTextMateService.ts: + 312 grammarFactory.setTheme(theme, tokenColorMap); + 313 let colorMap = AbstractTextMateService._toColorMap(tokenColorMap); + 314 let cssRules = generateTokensCSSForColorMap(colorMap); + 315: this._styleElement.innerHTML = cssRules; + 316 TokenizationRegistry.setColorMap(colorMap); + 317 } + 318 + +src/vs/workbench/services/themes/browser/workbenchThemeService.ts: + 692 const elStyle = document.createElement('style'); + 693 elStyle.type = 'text/css'; + 694 elStyle.className = rulesClassName; + 695: elStyle.innerHTML = styleSheetContent; + 696 document.head.appendChild(elStyle); + 697 } else { + 698: (themeStyles[0]).innerHTML = styleSheetContent; + 699 } + 700 } + 701 From a002404b2eadfb9d744d60f0dd7075c6cd00fc90 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 09:39:17 +0200 Subject: [PATCH 38/98] update notebooks --- .vscode/notebooks/api.github-issues | 2 +- .vscode/notebooks/my-work.github-issues | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/notebooks/api.github-issues b/.vscode/notebooks/api.github-issues index ad2d028465e..2eb4b6432b3 100644 --- a/.vscode/notebooks/api.github-issues +++ b/.vscode/notebooks/api.github-issues @@ -8,7 +8,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"August 2020\"", + "value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"September 2020\"", "editable": true }, { diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index d1452276f6e..a5de65e0bd1 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -8,7 +8,7 @@ { "kind": 2, "language": "github-issues", - "value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks\n\n// current milestone name\n$milestone=milestone:\"August 2020\"", + "value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks\n\n// current milestone name\n$milestone=milestone:\"September 2020\"", "editable": true }, { From 0d6a1f8e1c0d1dd4268b01f123505966b17eb66d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 09:42:19 +0200 Subject: [PATCH 39/98] TrustedTypes - use clearNode instead of innerHTML --- .vscode/searches/TrustedTypes.code-search | 12 +----------- .../notebook/browser/view/renderers/cellWidgets.ts | 4 ++-- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/.vscode/searches/TrustedTypes.code-search b/.vscode/searches/TrustedTypes.code-search index f4ded269d55..2112eb183c8 100644 --- a/.vscode/searches/TrustedTypes.code-search +++ b/.vscode/searches/TrustedTypes.code-search @@ -4,7 +4,7 @@ # Excluding: *.test.ts # ContextLines: 3 -59 results - 40 files +57 results - 39 files src/vs/base/browser/markdownRenderer.ts: 156 const strValue = values[0]; @@ -382,16 +382,6 @@ src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts: 604 return dragImageContainer; 605 } -src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts: - 77 return; - 78 } - 79 - 80: this.leftContributedItemsContainer.innerHTML = ''; - 81: this.rightContributedItemsContainer.innerHTML = ''; - 82 this.itemsDisposable.clear(); - 83 - 84 const items = this.notebookCellStatusBarService.getEntries(this.currentContext.cell.uri); - src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts: 375 addMouseoverListeners(outputNode, outputId); 376 const content = data.content; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts index fbb102133c1..41bb82bb695 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets.ts @@ -77,8 +77,8 @@ export class CellEditorStatusBar extends Disposable { return; } - this.leftContributedItemsContainer.innerHTML = ''; - this.rightContributedItemsContainer.innerHTML = ''; + DOM.clearNode(this.leftContributedItemsContainer); + DOM.clearNode(this.rightContributedItemsContainer); this.itemsDisposable.clear(); const items = this.notebookCellStatusBarService.getEntries(this.currentContext.cell.uri); From 82aa8fc425d976cceed8fc175a388f4b8e9ce640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Tue, 8 Sep 2020 09:55:07 +0200 Subject: [PATCH 40/98] better git and github docs --- extensions/git/package.nls.json | 4 ++-- extensions/github/package.nls.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index c412586f43c..b2aee5a34ba 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -166,8 +166,8 @@ "view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use git and source control in VS Code in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.", "view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.scm.folder": "The folder currently open doesn't have a git repository.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.scm.folder": "The folder currently open doesn't have a git repository. You can initialize a repository which will enable source control features powered by git.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories. You can initialize a repository on a folder which will enable source control features powered by git.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", "view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone)" } diff --git a/extensions/github/package.nls.json b/extensions/github/package.nls.json index 28906a39f0d..34e762b2f9c 100644 --- a/extensions/github/package.nls.json +++ b/extensions/github/package.nls.json @@ -2,6 +2,6 @@ "displayName": "GitHub", "description": "GitHub", "config.gitAuthentication": "Controls whether to enable automatic GitHub authentication for git commands within VS Code.", - "welcome.publishFolder": "You can also directly publish this folder to a GitHub repository.\n[$(github) Publish to GitHub](command:github.publish)", - "welcome.publishWorkspaceFolder": "You can also directly publish a workspace folder to a GitHub repository.\n[$(github) Publish to GitHub](command:github.publish)" + "welcome.publishFolder": "You can also directly publish this folder to a GitHub repository. Once published, you'll have access to source control features powered by git and GitHub.\n[$(github) Publish to GitHub](command:github.publish)", + "welcome.publishWorkspaceFolder": "You can also directly publish a workspace folder to a GitHub repository. Once published, you'll have access to source control features powered by git and GitHub.\n[$(github) Publish to GitHub](command:github.publish)" } From 7a6d2cad4fa6f9c914628cb42b1c594b7afc23af Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 10:19:00 +0200 Subject: [PATCH 41/98] :lipstick: some code lens polish --- src/vs/editor/contrib/codelens/codelens.ts | 61 ++++++++++--------- .../contrib/codelens/codelensController.ts | 20 +++--- .../api/extHostLanguageFeatures.test.ts | 8 +-- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/vs/editor/contrib/codelens/codelens.ts b/src/vs/editor/contrib/codelens/codelens.ts index 76c9cd84fd7..fbcfb19913b 100644 --- a/src/vs/editor/contrib/codelens/codelens.ts +++ b/src/vs/editor/contrib/codelens/codelens.ts @@ -36,44 +36,47 @@ export class CodeLensModel { } } -export function getCodeLensData(model: ITextModel, token: CancellationToken): Promise { +export async function getCodeLensModel(model: ITextModel, token: CancellationToken): Promise { const provider = CodeLensProviderRegistry.ordered(model); const providerRanks = new Map(); const result = new CodeLensModel(); - const promises = provider.map((provider, i) => { + const promises = provider.map(async (provider, i) => { providerRanks.set(provider, i); - return Promise.resolve(provider.provideCodeLenses(model, token)) - .then(list => list && result.add(list, provider)) - .catch(onUnexpectedExternalError); - }); - - return Promise.all(promises).then(() => { - - result.lenses = mergeSort(result.lenses, (a, b) => { - // sort by lineNumber, provider-rank, and column - if (a.symbol.range.startLineNumber < b.symbol.range.startLineNumber) { - return -1; - } else if (a.symbol.range.startLineNumber > b.symbol.range.startLineNumber) { - return 1; - } else if (providerRanks.get(a.provider)! < providerRanks.get(b.provider)!) { - return -1; - } else if (providerRanks.get(a.provider)! > providerRanks.get(b.provider)!) { - return 1; - } else if (a.symbol.range.startColumn < b.symbol.range.startColumn) { - return -1; - } else if (a.symbol.range.startColumn > b.symbol.range.startColumn) { - return 1; - } else { - return 0; + try { + const list = await Promise.resolve(provider.provideCodeLenses(model, token)); + if (list) { + result.add(list, provider); } - }); - - return result; + } catch (err) { + onUnexpectedExternalError(err); + } }); + + await Promise.all(promises); + + result.lenses = mergeSort(result.lenses, (a, b) => { + // sort by lineNumber, provider-rank, and column + if (a.symbol.range.startLineNumber < b.symbol.range.startLineNumber) { + return -1; + } else if (a.symbol.range.startLineNumber > b.symbol.range.startLineNumber) { + return 1; + } else if ((providerRanks.get(a.provider)!) < (providerRanks.get(b.provider)!)) { + return -1; + } else if ((providerRanks.get(a.provider)!) > (providerRanks.get(b.provider)!)) { + return 1; + } else if (a.symbol.range.startColumn < b.symbol.range.startColumn) { + return -1; + } else if (a.symbol.range.startColumn > b.symbol.range.startColumn) { + return 1; + } else { + return 0; + } + }); + return result; } registerLanguageCommand('_executeCodeLensProvider', function (accessor, args) { @@ -90,7 +93,7 @@ registerLanguageCommand('_executeCodeLensProvider', function (accessor, args) { const result: CodeLens[] = []; const disposables = new DisposableStore(); - return getCodeLensData(model, CancellationToken.None).then(value => { + return getCodeLensModel(model, CancellationToken.None).then(value => { disposables.add(value); let resolve: Promise[] = []; diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index 14e21796a7c..dba5288ef3d 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -12,7 +12,7 @@ import { registerEditorContribution, ServicesAccessor, registerEditorAction, Edi import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { IModelDecorationsChangeAccessor } from 'vs/editor/common/model'; import { CodeLensProviderRegistry, CodeLens, Command } from 'vs/editor/common/modes'; -import { CodeLensModel, getCodeLensData, CodeLensItem } from 'vs/editor/contrib/codelens/codelens'; +import { CodeLensModel, getCodeLensModel, CodeLensItem } from 'vs/editor/contrib/codelens/codelens'; import { CodeLensWidget, CodeLensHelper } from 'vs/editor/contrib/codelens/codelensWidget'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -35,7 +35,7 @@ export class CodeLensContribution implements IEditorContribution { private readonly _styleElement: HTMLStyleElement; private readonly _styleClassName: string; private _lenses: CodeLensWidget[] = []; - private _currentFindCodeLensSymbolsPromise: CancelablePromise | undefined; + private _currentGetCodeLensModel: CancelablePromise | undefined; private _oldCodeLensModels = new DisposableStore(); private _currentCodeLensModel: CodeLensModel | undefined; private _modelChangeCounter: number = 0; @@ -80,7 +80,7 @@ export class CodeLensContribution implements IEditorContribution { this._localDispose(); this._globalToDispose.dispose(); this._oldCodeLensModels.dispose(); - dispose(this._currentCodeLensModel); + this._currentCodeLensModel?.dispose(); } private _updateLensStyle(): void { @@ -99,9 +99,9 @@ export class CodeLensContribution implements IEditorContribution { } private _localDispose(): void { - if (this._currentFindCodeLensSymbolsPromise) { - this._currentFindCodeLensSymbolsPromise.cancel(); - this._currentFindCodeLensSymbolsPromise = undefined; + if (this._currentGetCodeLensModel) { + this._currentGetCodeLensModel.cancel(); + this._currentGetCodeLensModel = undefined; this._modelChangeCounter++; } if (this._currentResolveCodeLensSymbolsPromise) { @@ -157,13 +157,13 @@ export class CodeLensContribution implements IEditorContribution { const scheduler = new RunOnceScheduler(() => { const counterValue = ++this._modelChangeCounter; - if (this._currentFindCodeLensSymbolsPromise) { - this._currentFindCodeLensSymbolsPromise.cancel(); + if (this._currentGetCodeLensModel) { + this._currentGetCodeLensModel.cancel(); } - this._currentFindCodeLensSymbolsPromise = createCancelablePromise(token => getCodeLensData(model, token)); + this._currentGetCodeLensModel = createCancelablePromise(token => getCodeLensModel(model, token)); - this._currentFindCodeLensSymbolsPromise.then(result => { + this._currentGetCodeLensModel.then(result => { if (counterValue === this._modelChangeCounter) { // only the last one wins if (this._currentCodeLensModel) { this._oldCodeLensModels.add(this._currentCodeLensModel); diff --git a/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts index f6860e3f9c6..df33e67802a 100644 --- a/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/browser/api/extHostLanguageFeatures.test.ts @@ -22,7 +22,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { getDocumentSymbols } from 'vs/editor/contrib/gotoSymbol/documentSymbols'; import * as modes from 'vs/editor/common/modes'; -import { getCodeLensData } from 'vs/editor/contrib/codelens/codelens'; +import { getCodeLensModel } from 'vs/editor/contrib/codelens/codelens'; import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition, getDeclarationsAtPosition, getReferencesAtPosition } from 'vs/editor/contrib/gotoSymbol/goToSymbol'; import { getHover } from 'vs/editor/contrib/hover/getHover'; import { getOccurrencesAtPosition } from 'vs/editor/contrib/wordHighlighter/wordHighlighter'; @@ -189,7 +189,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getCodeLensData(model, CancellationToken.None); + const value = await getCodeLensModel(model, CancellationToken.None); assert.equal(value.lenses.length, 1); }); @@ -207,7 +207,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getCodeLensData(model, CancellationToken.None); + const value = await getCodeLensModel(model, CancellationToken.None); assert.equal(value.lenses.length, 1); const [data] = value.lenses; const symbol = await Promise.resolve(data.provider.resolveCodeLens!(model, data.symbol, CancellationToken.None)); @@ -224,7 +224,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await getCodeLensData(model, CancellationToken.None); + const value = await getCodeLensModel(model, CancellationToken.None); assert.equal(value.lenses.length, 1); let [data] = value.lenses; const symbol = await Promise.resolve(data.provider.resolveCodeLens!(model, data.symbol, CancellationToken.None)); From 42816198786a66875d4c23b91003d27569029e7e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 10:45:19 +0200 Subject: [PATCH 42/98] extract request delay managment for reuse, https://github.com/microsoft/vscode/issues/106267 --- .../common/modes/languageFeatureRegistry.ts | 42 +++++++++++++++++++ .../contrib/documentSymbols/outlineModel.ts | 21 ++-------- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/vs/editor/common/modes/languageFeatureRegistry.ts b/src/vs/editor/common/modes/languageFeatureRegistry.ts index 4278ec10e3a..cc59121efe0 100644 --- a/src/vs/editor/common/modes/languageFeatureRegistry.ts +++ b/src/vs/editor/common/modes/languageFeatureRegistry.ts @@ -4,7 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from 'vs/base/common/event'; +import { hash } from 'vs/base/common/hash'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { LRUCache } from 'vs/base/common/map'; +import { MovingAverage } from 'vs/base/common/numbers'; import { ITextModel } from 'vs/editor/common/model'; import { LanguageSelector, score } from 'vs/editor/common/modes/languageSelector'; import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService'; @@ -174,3 +177,42 @@ export class LanguageFeatureRegistry { } } } + + +export class LanguageFeatureRequestDelays { + + private readonly _cache = new LRUCache(50, 0.7); + + constructor( + private readonly _registry: LanguageFeatureRegistry, + readonly min: number, + readonly max: number = Number.MAX_SAFE_INTEGER, + ) { } + + private _key(model: ITextModel): string { + return model.id + hash(this._registry.all(model)); + } + + private _clamp(value: number | undefined): number { + if (value === undefined) { + return this.min; + } else { + return Math.min(this.max, Math.max(this.min, Math.floor(value * 1.3))); + } + } + + get(model: ITextModel): number { + const key = this._key(model); + return this._clamp(this._cache.get(key)?.value); + } + + update(model: ITextModel, value: number) { + const key = this._key(model); + let avg = this._cache.get(key); + if (!avg) { + avg = new MovingAverage(); + this._cache.set(key, avg); + } + avg.update(value); + } +} diff --git a/src/vs/editor/contrib/documentSymbols/outlineModel.ts b/src/vs/editor/contrib/documentSymbols/outlineModel.ts index d9e102ee50c..c85081502dd 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineModel.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineModel.ts @@ -14,8 +14,8 @@ import { ITextModel } from 'vs/editor/common/model'; import { DocumentSymbol, DocumentSymbolProvider, DocumentSymbolProviderRegistry } from 'vs/editor/common/modes'; import { MarkerSeverity } from 'vs/platform/markers/common/markers'; import { Iterable } from 'vs/base/common/iterator'; -import { MovingAverage } from 'vs/base/common/numbers'; import { URI } from 'vs/base/common/uri'; +import { LanguageFeatureRequestDelays } from 'vs/editor/common/modes/languageFeatureRegistry'; export abstract class TreeElement { @@ -208,7 +208,7 @@ export class OutlineGroup extends TreeElement { export class OutlineModel extends TreeElement { - private static readonly _requestDurations = new LRUCache(50, 0.7); + private static readonly _requestDurations = new LanguageFeatureRequestDelays(DocumentSymbolProviderRegistry, 350); private static readonly _requests = new LRUCache, model: OutlineModel | undefined }>(9, 0.75); private static readonly _keys = new class { @@ -252,13 +252,7 @@ export class OutlineModel extends TreeElement { // keep moving average of request durations const now = Date.now(); data.promise.then(() => { - let key = this._keys.for(textModel, false); - let avg = this._requestDurations.get(key); - if (!avg) { - avg = new MovingAverage(); - this._requestDurations.set(key, avg); - } - avg.update(Date.now() - now); + this._requestDurations.update(textModel, Date.now() - now); }); } @@ -290,14 +284,7 @@ export class OutlineModel extends TreeElement { } static getRequestDelay(textModel: ITextModel | null): number { - if (!textModel) { - return 350; - } - const avg = this._requestDurations.get(this._keys.for(textModel, false)); - if (!avg) { - return 350; - } - return Math.max(350, Math.floor(1.3 * avg.value)); + return textModel ? this._requestDurations.get(textModel) : this._requestDurations.min; } private static _create(textModel: ITextModel, token: CancellationToken): Promise { From 707ce447cb14b0d40bdd9d348ef6d6afc381f38e Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Sep 2020 10:52:03 +0200 Subject: [PATCH 43/98] fixes #106246 --- src/vs/workbench/contrib/files/browser/fileCommands.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index eae180f51c0..6549ba4fdcc 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -74,8 +74,8 @@ export const SAVE_ALL_IN_GROUP_COMMAND_ID = 'workbench.files.action.saveAllInGro export const SAVE_FILES_COMMAND_ID = 'workbench.action.files.saveFiles'; export const OpenEditorsGroupContext = new RawContextKey('groupFocusedInOpenEditors', false); -export const DirtyEditorContext = new RawContextKey('dirtyEditor', false); -export const ReadonlyEditorContext = new RawContextKey('readonlyEditor', false); +export const DirtyEditorContext = new RawContextKey('dirtyEditorFocusedInOpenEditors', false); +export const ReadonlyEditorContext = new RawContextKey('readonlyEditorFocusedInOpenEditors', false); export const ResourceSelectedForCompareContext = new RawContextKey('resourceSelectedForCompare', false); export const REMOVE_ROOT_FOLDER_COMMAND_ID = 'removeRootFolder'; From 0a22f4cc42f305b7c9a30920878281d375b79d30 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Sep 2020 11:14:18 +0200 Subject: [PATCH 44/98] more colorScheme adoption --- src/vs/code/electron-browser/workbench/workbench.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 631ddb651e6..f44b74ffc7d 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -76,7 +76,7 @@ bootstrapWindow.load([ /** * @param {{ * partsSplashPath?: string, - * colorScheme: (1 | 2 | 3), + * colorScheme: ('light' | 'dark' | 'hc'), * autoDetectHighContrast?: boolean, * extensionDevelopmentPath?: string[], * folderUri?: object, @@ -96,7 +96,7 @@ function showPartsSplash(configuration) { } // high contrast mode has been turned on from the outside, e.g. OS -> ignore stored colors and layouts - const isHighContrast = configuration.colorScheme === 3 /* ColorScheme.HIGH_CONTRAST */ && configuration.autoDetectHighContrast; + const isHighContrast = configuration.colorScheme === 'hc' /* ColorScheme.HIGH_CONTRAST */ && configuration.autoDetectHighContrast; if (data && isHighContrast && data.baseTheme !== 'hc-black') { data = undefined; } From 80513ce407f9b501482a27e77d4ae62a5702da6b Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Sep 2020 11:14:40 +0200 Subject: [PATCH 45/98] add HostColorService --- .../host/browser/browserHostService.ts | 13 ----- .../workbench/services/host/browser/host.ts | 11 ----- .../electron-sandbox/nativeHostService.ts | 27 +--------- .../themes/browser/browserHostColorService.ts | 49 +++++++++++++++++++ .../themes/browser/workbenchThemeService.ts | 10 ++-- .../themes/common/hostColorService.ts | 19 +++++++ .../nativeHostColorService.ts | 45 +++++++++++++++++ src/vs/workbench/workbench.sandbox.main.ts | 1 + src/vs/workbench/workbench.web.main.ts | 1 + 9 files changed, 121 insertions(+), 55 deletions(-) create mode 100644 src/vs/workbench/services/themes/browser/browserHostColorService.ts create mode 100644 src/vs/workbench/services/themes/common/hostColorService.ts create mode 100644 src/vs/workbench/services/themes/electron-sandbox/nativeHostColorService.ts diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index 2c81c587686..6ac6cdd6c86 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -329,19 +329,6 @@ export class BrowserHostService extends Disposable implements IHostService { //#endregion - - //#region Color Scheme - - // TODO@martin TODO@ben this currently does not support detecting changes - onDidChangeColorScheme = Event.None; - - get colorScheme() { - return this.environmentService.configuration.colorScheme; - } - - //#endregion - - //#region Lifecycle async restart(): Promise { diff --git a/src/vs/workbench/services/host/browser/host.ts b/src/vs/workbench/services/host/browser/host.ts index c10f8c651ac..25f16cf7b07 100644 --- a/src/vs/workbench/services/host/browser/host.ts +++ b/src/vs/workbench/services/host/browser/host.ts @@ -5,7 +5,6 @@ import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { ColorScheme } from 'vs/platform/theme/common/theme'; import { IWindowOpenable, IOpenWindowOptions, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; export const IHostService = createDecorator('hostService'); @@ -66,16 +65,6 @@ export interface IHostService { //#endregion - - //#region Color Scheme - - readonly colorScheme: ColorScheme; - - readonly onDidChangeColorScheme: Event; - - //#endregion - - //#region Lifecycle /** diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 85cf4ab0827..94a0121afd1 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Emitter, Event } from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -11,7 +11,6 @@ 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 { ColorScheme } from 'vs/platform/theme/common/theme'; export class NativeHostService extends Disposable implements IHostService { @@ -23,21 +22,8 @@ export class NativeHostService extends Disposable implements IHostService { @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService ) { super(); - - this.registerListeners(); } - private registerListeners(): void { - - // Color Scheme - this._register(this.electronService.onColorSchemeChange(scheme => { - this._colorScheme = scheme; - - this._onDidChangeColorScheme.fire(); - })); - } - - //#region Focus get onDidChangeFocus(): Event { return this._onDidChangeFocus; } @@ -106,17 +92,6 @@ export class NativeHostService extends Disposable implements IHostService { //#endregion - //#region Color Scheme - - private readonly _onDidChangeColorScheme = this._register(new Emitter()); - readonly onDidChangeColorScheme = this._onDidChangeColorScheme.event; - - private _colorScheme: ColorScheme = this.environmentService.configuration.colorScheme; - get colorScheme() { return this._colorScheme; } - - //#endregion - - //#region Lifecycle focus(options?: { force: boolean }): Promise { diff --git a/src/vs/workbench/services/themes/browser/browserHostColorService.ts b/src/vs/workbench/services/themes/browser/browserHostColorService.ts new file mode 100644 index 00000000000..71ca270e6a6 --- /dev/null +++ b/src/vs/workbench/services/themes/browser/browserHostColorService.ts @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter, Event } from 'vs/base/common/event'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { IHostColorService } from 'vs/workbench/services/themes/common/hostColorService'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; + +export class BrowserHostColorService extends Disposable implements IHostColorService { + + declare readonly _serviceBrand: undefined; + + private readonly _onDidSchemeChangeEvent = this._register(new Emitter()); + + constructor( + @IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService + ) { + super(); + + this.registerListeners(); + } + + private registerListeners(): void { + + window.matchMedia('(prefers-color-scheme: dark)').addListener(() => { + this._onDidSchemeChangeEvent.fire(); + }); + } + + get onDidChangeColorScheme(): Event { + return this._onDidSchemeChangeEvent.event; + } + + get colorScheme(): ColorScheme { + if (window.matchMedia(`(prefers-color-scheme: light)`).matches) { + return ColorScheme.LIGHT; + } else if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) { + return ColorScheme.DARK; + } + return this.environmentService.configuration.colorScheme; + } + +} + +registerSingleton(IHostColorService, BrowserHostColorService, true); diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index 0c2813d013b..a8ac5971cc0 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -35,7 +35,7 @@ import { registerProductIconThemeSchemas } from 'vs/workbench/services/themes/co import { ILogService } from 'vs/platform/log/common/log'; import { isWeb } from 'vs/base/common/platform'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -import { IHostService } from 'vs/workbench/services/host/browser/host'; +import { IHostColorService } from 'vs/workbench/services/themes/common/hostColorService'; // implementation @@ -106,7 +106,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { @IExtensionResourceLoaderService private readonly extensionResourceLoaderService: IExtensionResourceLoaderService, @IWorkbenchLayoutService readonly layoutService: IWorkbenchLayoutService, @ILogService private readonly logService: ILogService, - @IHostService private readonly hostService: IHostService, + @IHostColorService private readonly hostColorService: IHostColorService, ) { this.container = layoutService.container; this.settings = new ThemeConfiguration(configurationService); @@ -325,7 +325,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { // preferred scheme handling private installPreferredSchemeListener() { - this.hostService.onDidChangeColorScheme(() => this.handlePreferredSchemeUpdated()); + this.hostColorService.onDidChangeColorScheme(() => this.handlePreferredSchemeUpdated()); } private async handlePreferredSchemeUpdated() { @@ -352,11 +352,11 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { private getPreferredColorScheme(): ColorScheme | undefined { const detectHCThemeSetting = this.configurationService.getValue(ThemeSettings.DETECT_HC); - if (this.hostService.colorScheme === ColorScheme.HIGH_CONTRAST && detectHCThemeSetting) { + if (this.hostColorService.colorScheme === ColorScheme.HIGH_CONTRAST && detectHCThemeSetting) { return ColorScheme.HIGH_CONTRAST; } if (this.configurationService.getValue(ThemeSettings.DETECT_COLOR_SCHEME)) { - const osScheme = this.hostService.colorScheme; + const osScheme = this.hostColorService.colorScheme; if (osScheme !== ColorScheme.HIGH_CONTRAST) { return osScheme; } diff --git a/src/vs/workbench/services/themes/common/hostColorService.ts b/src/vs/workbench/services/themes/common/hostColorService.ts new file mode 100644 index 00000000000..c10d23e2dc0 --- /dev/null +++ b/src/vs/workbench/services/themes/common/hostColorService.ts @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; + +export const IHostColorService = createDecorator('hostColorService'); + +export interface IHostColorService { + + readonly _serviceBrand: undefined; + + readonly colorScheme: ColorScheme; + readonly onDidChangeColorScheme: Event; + +} diff --git a/src/vs/workbench/services/themes/electron-sandbox/nativeHostColorService.ts b/src/vs/workbench/services/themes/electron-sandbox/nativeHostColorService.ts new file mode 100644 index 00000000000..cac81330b3e --- /dev/null +++ b/src/vs/workbench/services/themes/electron-sandbox/nativeHostColorService.ts @@ -0,0 +1,45 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter } from 'vs/base/common/event'; +import { IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; +import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { ColorScheme } from 'vs/platform/theme/common/theme'; +import { IHostColorService } from 'vs/workbench/services/themes/common/hostColorService'; + +export class NativeHostColorService extends Disposable implements IHostColorService { + + declare readonly _serviceBrand: undefined; + + constructor( + @IElectronService private readonly electronService: IElectronService, + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService + ) { + super(); + + this.registerListeners(); + } + + private registerListeners(): void { + + // Color Scheme + this._register(this.electronService.onColorSchemeChange(scheme => { + this._colorScheme = scheme; + + this._onDidChangeColorScheme.fire(); + })); + } + + private readonly _onDidChangeColorScheme = this._register(new Emitter()); + readonly onDidChangeColorScheme = this._onDidChangeColorScheme.event; + + private _colorScheme: ColorScheme = this.environmentService.configuration.colorScheme; + get colorScheme() { return this._colorScheme; } + +} + +registerSingleton(IHostColorService, NativeHostColorService, true); diff --git a/src/vs/workbench/workbench.sandbox.main.ts b/src/vs/workbench/workbench.sandbox.main.ts index d0ec888aac6..63d0c766333 100644 --- a/src/vs/workbench/workbench.sandbox.main.ts +++ b/src/vs/workbench/workbench.sandbox.main.ts @@ -38,6 +38,7 @@ import 'vs/workbench/services/workspaces/electron-sandbox/workspaceEditingServic import 'vs/workbench/services/configurationResolver/electron-sandbox/configurationResolverService'; import 'vs/workbench/services/accessibility/electron-sandbox/accessibilityService'; import 'vs/workbench/services/path/electron-sandbox/pathService'; +import 'vs/workbench/services/themes/electron-sandbox/nativeHostColorService'; //#endregion diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index f02bbbf874b..74a2a17e1a8 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -50,6 +50,7 @@ import 'vs/workbench/services/lifecycle/browser/lifecycleService'; import 'vs/workbench/services/clipboard/browser/clipboardService'; import 'vs/workbench/services/extensionResourceLoader/browser/extensionResourceLoaderService'; import 'vs/workbench/services/path/browser/pathService'; +import 'vs/workbench/services/themes/browser/browserHostColorService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; From 4a801b9737c804cfd79997100967735e28b353eb Mon Sep 17 00:00:00 2001 From: mbassit Date: Tue, 8 Sep 2020 10:19:39 +0100 Subject: [PATCH 46/98] Increased height of proxy authentication dialog to prevent cutting buttons (#83900) --- src/vs/code/electron-main/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/auth.ts b/src/vs/code/electron-main/auth.ts index c1e2a84946a..ca071cf2836 100644 --- a/src/vs/code/electron-main/auth.ts +++ b/src/vs/code/electron-main/auth.ts @@ -55,7 +55,7 @@ export class ProxyAuthHandler extends Disposable { skipTaskbar: true, resizable: false, width: 450, - height: 220, + height: 225, show: true, title: 'VS Code', webPreferences: { From 89a2e78f7c43a7ea377e0d6a4a0e5ad81f326e38 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 11:25:11 +0200 Subject: [PATCH 47/98] adopt request delays in code lense, also modernize code lens. fixes https://github.com/microsoft/vscode/issues/106267 --- .../common/modes/languageFeatureRegistry.ts | 4 + .../contrib/codelens/codelensController.ts | 146 +++++++++--------- 2 files changed, 78 insertions(+), 72 deletions(-) diff --git a/src/vs/editor/common/modes/languageFeatureRegistry.ts b/src/vs/editor/common/modes/languageFeatureRegistry.ts index cc59121efe0..3a19ca1acf8 100644 --- a/src/vs/editor/common/modes/languageFeatureRegistry.ts +++ b/src/vs/editor/common/modes/languageFeatureRegistry.ts @@ -179,6 +179,10 @@ export class LanguageFeatureRegistry { } +/** + * Keeps moving average per model and set of providers so that requests + * can be debounce according to the provider performance + */ export class LanguageFeatureRequestDelays { private readonly _cache = new LRUCache(50, 0.7); diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index dba5288ef3d..e61869e3c80 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -5,7 +5,7 @@ import { CancelablePromise, RunOnceScheduler, createCancelablePromise, disposableTimeout } from 'vs/base/common/async'; import { onUnexpectedError, onUnexpectedExternalError } from 'vs/base/common/errors'; -import { toDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; +import { toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { StableEditorScrollState } from 'vs/editor/browser/core/editorState'; import { ICodeEditor, MouseTargetType, IViewZoneChangeAccessor, IActiveCodeEditor } from 'vs/editor/browser/editorBrowser'; import { registerEditorContribution, ServicesAccessor, registerEditorAction, EditorAction } from 'vs/editor/browser/editorExtensions'; @@ -23,24 +23,25 @@ import { hash } from 'vs/base/common/hash'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { localize } from 'vs/nls'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { LanguageFeatureRequestDelays } from 'vs/editor/common/modes/languageFeatureRegistry'; export class CodeLensContribution implements IEditorContribution { - public static readonly ID: string = 'css.editor.codeLens'; + static readonly ID: string = 'css.editor.codeLens'; - private _isEnabled: boolean; - - private readonly _globalToDispose = new DisposableStore(); + private readonly _disposables = new DisposableStore(); private readonly _localToDispose = new DisposableStore(); private readonly _styleElement: HTMLStyleElement; private readonly _styleClassName: string; - private _lenses: CodeLensWidget[] = []; - private _currentGetCodeLensModel: CancelablePromise | undefined; + private readonly _lenses: CodeLensWidget[] = []; + + private readonly _getCodeLensModelDelays = new LanguageFeatureRequestDelays(CodeLensProviderRegistry, 250, 2500); + private _getCodeLensModelPromise: CancelablePromise | undefined; private _oldCodeLensModels = new DisposableStore(); private _currentCodeLensModel: CodeLensModel | undefined; - private _modelChangeCounter: number = 0; - private _currentResolveCodeLensSymbolsPromise: CancelablePromise | undefined; - private _detectVisibleLenses: RunOnceScheduler | undefined; + private readonly _resolveCodeLensesDelays = new LanguageFeatureRequestDelays(CodeLensProviderRegistry, 250, 2500); + private readonly _resolveCodeLensesScheduler = new RunOnceScheduler(() => this._resolveCodeLensesInViewport(), this._resolveCodeLensesDelays.min); + private _resolveCodeLensesPromise: CancelablePromise | undefined; constructor( private readonly _editor: ICodeEditor, @@ -48,23 +49,18 @@ export class CodeLensContribution implements IEditorContribution { @INotificationService private readonly _notificationService: INotificationService, @ICodeLensCache private readonly _codeLensCache: ICodeLensCache ) { - this._isEnabled = this._editor.getOption(EditorOption.codeLens); - this._globalToDispose.add(this._editor.onDidChangeModel(() => this._onModelChange())); - this._globalToDispose.add(this._editor.onDidChangeModelLanguage(() => this._onModelChange())); - this._globalToDispose.add(this._editor.onDidChangeConfiguration(() => { - const prevIsEnabled = this._isEnabled; - this._isEnabled = this._editor.getOption(EditorOption.codeLens); - if (prevIsEnabled !== this._isEnabled) { - this._onModelChange(); - } - })); - this._globalToDispose.add(CodeLensProviderRegistry.onDidChange(this._onModelChange, this)); - this._globalToDispose.add(this._editor.onDidChangeConfiguration(e => { + this._disposables.add(this._editor.onDidChangeModel(() => this._onModelChange())); + this._disposables.add(this._editor.onDidChangeModelLanguage(() => this._onModelChange())); + this._disposables.add(this._editor.onDidChangeConfiguration((e) => { if (e.hasChanged(EditorOption.fontInfo)) { this._updateLensStyle(); } + if (e.hasChanged(EditorOption.codeLens)) { + this._onModelChange(); + } })); + this._disposables.add(CodeLensProviderRegistry.onDidChange(this._onModelChange, this)); this._onModelChange(); this._styleClassName = '_' + hash(this._editor.getId()).toString(16); @@ -78,7 +74,7 @@ export class CodeLensContribution implements IEditorContribution { dispose(): void { this._localDispose(); - this._globalToDispose.dispose(); + this._disposables.dispose(); this._oldCodeLensModels.dispose(); this._currentCodeLensModel?.dispose(); } @@ -99,18 +95,13 @@ export class CodeLensContribution implements IEditorContribution { } private _localDispose(): void { - if (this._currentGetCodeLensModel) { - this._currentGetCodeLensModel.cancel(); - this._currentGetCodeLensModel = undefined; - this._modelChangeCounter++; - } - if (this._currentResolveCodeLensSymbolsPromise) { - this._currentResolveCodeLensSymbolsPromise.cancel(); - this._currentResolveCodeLensSymbolsPromise = undefined; - } + this._getCodeLensModelPromise?.cancel(); + this._getCodeLensModelPromise = undefined; + this._resolveCodeLensesPromise?.cancel(); + this._resolveCodeLensesPromise = undefined; this._localToDispose.clear(); this._oldCodeLensModels.clear(); - dispose(this._currentCodeLensModel); + this._currentCodeLensModel?.dispose(); } private _onModelChange(): void { @@ -122,7 +113,7 @@ export class CodeLensContribution implements IEditorContribution { return; } - if (!this._isEnabled) { + if (!this._editor.getOption(EditorOption.codeLens)) { return; } @@ -153,34 +144,33 @@ export class CodeLensContribution implements IEditorContribution { } } - const detectVisibleLenses = this._detectVisibleLenses = new RunOnceScheduler(() => this._onViewportChanged(), 250); - const scheduler = new RunOnceScheduler(() => { - const counterValue = ++this._modelChangeCounter; - if (this._currentGetCodeLensModel) { - this._currentGetCodeLensModel.cancel(); - } + const t1 = Date.now(); - this._currentGetCodeLensModel = createCancelablePromise(token => getCodeLensModel(model, token)); + this._getCodeLensModelPromise?.cancel(); + this._getCodeLensModelPromise = createCancelablePromise(token => getCodeLensModel(model, token)); - this._currentGetCodeLensModel.then(result => { - if (counterValue === this._modelChangeCounter) { // only the last one wins - if (this._currentCodeLensModel) { - this._oldCodeLensModels.add(this._currentCodeLensModel); - } - this._currentCodeLensModel = result; - - // cache model to reduce flicker - this._codeLensCache.put(model, result); - - // render lenses - this._renderCodeLensSymbols(result); - detectVisibleLenses.schedule(); + this._getCodeLensModelPromise.then(result => { + if (this._currentCodeLensModel) { + this._oldCodeLensModels.add(this._currentCodeLensModel); } + this._currentCodeLensModel = result; + + // cache model to reduce flicker + this._codeLensCache.put(model, result); + + // update moving average + this._getCodeLensModelDelays.update(model, Date.now() - t1); + + // render lenses + this._renderCodeLensSymbols(result); + this._resolveCodeLensesInViewportSoon(); }, onUnexpectedError); - }, 250); + + }, this._getCodeLensModelDelays.get(model)); + this._localToDispose.add(scheduler); - this._localToDispose.add(detectVisibleLenses); + this._localToDispose.add(toDisposable(() => this._resolveCodeLensesScheduler.cancel())); this._localToDispose.add(this._editor.onDidChangeModelContent(() => { this._editor.changeDecorations(decorationsAccessor => { this._editor.changeViewZones(viewZonesAccessor => { @@ -209,17 +199,17 @@ export class CodeLensContribution implements IEditorContribution { }); // Compute new `visible` code lenses - detectVisibleLenses.schedule(); + this._resolveCodeLensesInViewportSoon(); // Ask for all references again scheduler.schedule(); })); this._localToDispose.add(this._editor.onDidScrollChange(e => { if (e.scrollTopChanged && this._lenses.length > 0) { - detectVisibleLenses.schedule(); + this._resolveCodeLensesInViewportSoon(); } })); this._localToDispose.add(this._editor.onDidLayoutChange(() => { - detectVisibleLenses.schedule(); + this._resolveCodeLensesInViewportSoon(); })); this._localToDispose.add(toDisposable(() => { if (this._editor.getModel()) { @@ -264,7 +254,7 @@ export class CodeLensContribution implements IEditorContribution { if (decChangeAccessor) { helper.commit(decChangeAccessor); } - this._lenses = []; + this._lenses.length = 0; } private _renderCodeLensSymbols(symbols: CodeLensModel): void { @@ -313,7 +303,7 @@ export class CodeLensContribution implements IEditorContribution { groupsIndex++; codeLensIndex++; } else { - this._lenses.splice(codeLensIndex, 0, new CodeLensWidget(groups[groupsIndex], this._editor, this._styleClassName, helper, viewZoneAccessor, () => this._detectVisibleLenses && this._detectVisibleLenses.schedule())); + this._lenses.splice(codeLensIndex, 0, new CodeLensWidget(groups[groupsIndex], this._editor, this._styleClassName, helper, viewZoneAccessor, () => this._resolveCodeLensesInViewportSoon())); codeLensIndex++; groupsIndex++; } @@ -327,7 +317,7 @@ export class CodeLensContribution implements IEditorContribution { // Create extra symbols while (groupsIndex < groups.length) { - this._lenses.push(new CodeLensWidget(groups[groupsIndex], this._editor, this._styleClassName, helper, viewZoneAccessor, () => this._detectVisibleLenses && this._detectVisibleLenses.schedule())); + this._lenses.push(new CodeLensWidget(groups[groupsIndex], this._editor, this._styleClassName, helper, viewZoneAccessor, () => this._resolveCodeLensesInViewportSoon())); groupsIndex++; } @@ -338,11 +328,17 @@ export class CodeLensContribution implements IEditorContribution { scrollState.restore(this._editor); } - private _onViewportChanged(): void { - if (this._currentResolveCodeLensSymbolsPromise) { - this._currentResolveCodeLensSymbolsPromise.cancel(); - this._currentResolveCodeLensSymbolsPromise = undefined; + private _resolveCodeLensesInViewportSoon(): void { + const model = this._editor.getModel(); + if (model) { + this._resolveCodeLensesScheduler.schedule(this._resolveCodeLensesDelays.get(model)); } + } + + private _resolveCodeLensesInViewport(): void { + + this._resolveCodeLensesPromise?.cancel(); + this._resolveCodeLensesPromise = undefined; const model = this._editor.getModel(); if (!model) { @@ -363,6 +359,8 @@ export class CodeLensContribution implements IEditorContribution { return; } + const t1 = Date.now(); + const resolvePromise = createCancelablePromise(token => { const promises = toResolve.map((request, i) => { @@ -388,20 +386,24 @@ export class CodeLensContribution implements IEditorContribution { return Promise.all(promises); }); - this._currentResolveCodeLensSymbolsPromise = resolvePromise; + this._resolveCodeLensesPromise = resolvePromise; + + this._resolveCodeLensesPromise.then(() => { + + // update moving average + this._resolveCodeLensesDelays.update(model, Date.now() - t1); - this._currentResolveCodeLensSymbolsPromise.then(() => { if (this._currentCodeLensModel) { // update the cached state with new resolved items this._codeLensCache.put(model, this._currentCodeLensModel); } this._oldCodeLensModels.clear(); // dispose old models once we have updated the UI with the current model - if (resolvePromise === this._currentResolveCodeLensSymbolsPromise) { - this._currentResolveCodeLensSymbolsPromise = undefined; + if (resolvePromise === this._resolveCodeLensesPromise) { + this._resolveCodeLensesPromise = undefined; } }, err => { onUnexpectedError(err); // can also be cancellation! - if (resolvePromise === this._currentResolveCodeLensSymbolsPromise) { - this._currentResolveCodeLensSymbolsPromise = undefined; + if (resolvePromise === this._resolveCodeLensesPromise) { + this._resolveCodeLensesPromise = undefined; } }); } From b1a66b59b8058a46c98c749623e420340dd958ac Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Sep 2020 11:53:59 +0200 Subject: [PATCH 48/98] debug: dynamic launch configurations should be stored properly fixes #96293 --- .../debug/browser/debugActionViewItems.ts | 10 ++--- .../browser/debugConfigurationManager.ts | 38 +++++++++++++++---- .../contrib/debug/browser/debugQuickAccess.ts | 2 +- .../workbench/contrib/debug/common/debug.ts | 4 +- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts index 4b3c2a72a1c..774e0b74dde 100644 --- a/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts +++ b/src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts @@ -11,7 +11,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { SelectBox, ISelectOptionItem } from 'vs/base/browser/ui/selectBox/selectBox'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IDebugService, IDebugSession, IDebugConfiguration, IConfig, ILaunch } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugService, IDebugSession, IDebugConfiguration, IConfig, ILaunch, IDebugConfigurationProvider } from 'vs/workbench/contrib/debug/common/debug'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { selectBorder, selectBackground } from 'vs/platform/theme/common/colorRegistry'; @@ -34,7 +34,7 @@ export class StartDebugActionViewItem implements IActionViewItem { private options: { label: string, handler: (() => Promise) }[] = []; private toDispose: IDisposable[]; private selected = 0; - private providers: { label: string, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[] = []; + private providers: { label: string, provider: IDebugConfigurationProvider, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[] = []; constructor( private context: unknown, @@ -182,7 +182,7 @@ export class StartDebugActionViewItem implements IActionViewItem { const label = inWorkspace ? `${name} (${launch.name})` : name; this.options.push({ label, handler: async () => { - manager.selectConfiguration(launch, name); + await manager.selectConfiguration(launch, name); return true; } }); @@ -196,7 +196,7 @@ export class StartDebugActionViewItem implements IActionViewItem { } this.providers.forEach(p => { - if (p.label === manager.selectedConfiguration.name) { + if (p.provider.type === manager.selectedConfiguration.config?.type) { this.selected = this.options.length; } @@ -204,7 +204,7 @@ export class StartDebugActionViewItem implements IActionViewItem { label: `${p.label}...`, handler: async () => { const picked = await p.pick(); if (picked) { - manager.selectConfiguration(picked.launch, p.label, picked.config); + await manager.selectConfiguration(picked.launch, picked.config.name, picked.config); return true; } return false; diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index e28eaf83505..7cc46462c3f 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -46,6 +46,8 @@ jsonRegistry.registerSchema(launchSchemaId, launchSchema); const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; const DEBUG_SELECTED_ROOT = 'debug.selectedroot'; +// Debug type is only stored if a dynamic configuration is used for better restore +const DEBUG_SELECTED_TYPE = 'debug.selectedtype'; interface IDynamicPickItem { label: string, launch: ILaunch, config: IConfig } @@ -84,13 +86,15 @@ export class ConfigurationManager implements IConfigurationManager { this.initLaunches(); this.registerListeners(); const previousSelectedRoot = this.storageService.get(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE); + const previousSelectedType = this.storageService.get(DEBUG_SELECTED_TYPE, StorageScope.WORKSPACE); const previousSelectedLaunch = this.launches.find(l => l.uri.toString() === previousSelectedRoot); + const previousSelectedName = this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE); this.debugConfigurationTypeContext = CONTEXT_DEBUG_CONFIGURATION_TYPE.bindTo(contextKeyService); this.debuggersAvailable = CONTEXT_DEBUGGERS_AVAILABLE.bindTo(contextKeyService); if (previousSelectedLaunch && previousSelectedLaunch.getConfigurationNames().length) { - this.selectConfiguration(previousSelectedLaunch, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE)); + this.selectConfiguration(previousSelectedLaunch, previousSelectedName, undefined, previousSelectedType); } else if (this.launches.length > 0) { - this.selectConfiguration(undefined); + this.selectConfiguration(undefined, previousSelectedName, undefined, previousSelectedType); } } @@ -259,7 +263,7 @@ export class ConfigurationManager implements IConfigurationManager { return results.reduce((first, second) => first.concat(second), []); } - async getDynamicProviders(): Promise<{ label: string, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[]> { + async getDynamicProviders(): Promise<{ label: string, provider: IDebugConfigurationProvider, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[]> { const extensions = await this.extensionService.getExtensions(); const onDebugDynamicConfigurationsName = 'onDebugDynamicConfigurations'; const debugDynamicExtensionsTypes = extensions.reduce((acc, e) => { @@ -289,9 +293,12 @@ export class ConfigurationManager implements IConfigurationManager { return acc; }, [] as string[]); + await Promise.all(debugDynamicExtensionsTypes.map(type => this.activateDebuggers(onDebugDynamicConfigurationsName, type))); return debugDynamicExtensionsTypes.map(type => { + const provider = this.configProviders.find(p => p.type === type && p.triggerKind === DebugConfigurationProviderTriggerKind.Dynamic && p.provideDebugConfigurations)!; return { label: this.getDebuggerLabel(type)!, + provider, pick: async () => { const disposables = new DisposableStore(); const input = disposables.add(this.quickInputService.createQuickPick()); @@ -308,15 +315,13 @@ export class ConfigurationManager implements IConfigurationManager { await launch.openConfigFile(false, config.type); // Only Launch have a pin trigger button await (launch as Launch).writeConfiguration(config); - this.selectConfiguration(launch, config.name); + await this.selectConfiguration(launch, config.name); })); disposables.add(input.onDidHide(() => { chosenDidCancel = true; resolve(); })); }); - await this.activateDebuggers(onDebugDynamicConfigurationsName, type); const token = new CancellationTokenSource(); const picks: Promise[] = []; - const provider = this.configProviders.filter(p => p.type === type && p.triggerKind === DebugConfigurationProviderTriggerKind.Dynamic && p.provideDebugConfigurations)[0]; this.getLaunches().forEach(launch => { if (launch.workspace && provider) { picks.push(provider.provideDebugConfigurations!(launch.workspace.uri, token.token).then(configurations => configurations.map(config => ({ @@ -508,7 +513,7 @@ export class ConfigurationManager implements IConfigurationManager { return undefined; } - selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig): void { + async selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig, type?: string): Promise { if (typeof launch === 'undefined') { const rootUri = this.historyService.getLastActiveWorkspaceRoot(); launch = this.getLaunch(rootUri); @@ -526,14 +531,31 @@ export class ConfigurationManager implements IConfigurationManager { } else { this.storageService.remove(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE); } + const names = launch ? launch.getConfigurationNames() : []; if ((name && names.indexOf(name) >= 0) || config) { this.setSelectedLaunchName(name); } else if (!this.selectedName || names.indexOf(this.selectedName) === -1) { - this.setSelectedLaunchName(names.length ? names[0] : undefined); + // We could not find the previously used name. We should get all dynamic configurations from providers + // And potentially auto select the previously used dynamic configuration #96293 + const providers = await this.getDynamicProviders(); + const provider = providers.find(p => p.provider.type === type); + let nameToSet = names.length ? names[0] : undefined; + if (provider && launch && launch.workspace) { + const token = new CancellationTokenSource(); + const dynamicConfigs = await provider.provider.provideDebugConfigurations!(launch.workspace.uri, token.token); + const dynamicConfig = dynamicConfigs.find(c => c.name === name); + if (dynamicConfig) { + config = dynamicConfig; + nameToSet = name; + } + } + + this.setSelectedLaunchName(nameToSet); } this.selectedConfig = config; + this.storageService.store(DEBUG_SELECTED_TYPE, this.selectedConfig?.type, StorageScope.WORKSPACE); const configForType = this.selectedConfig || (this.selectedLaunch && this.selectedName ? this.selectedLaunch.getConfiguration(this.selectedName) : undefined); if (configForType) { this.debugConfigurationTypeContext.set(configForType.type); diff --git a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts index cec5357ecc9..b8aac7951fb 100644 --- a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts +++ b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts @@ -64,7 +64,7 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider { - this.debugService.getConfigurationManager().selectConfiguration(config.launch, config.name); + await this.debugService.getConfigurationManager().selectConfiguration(config.launch, config.name); try { await this.debugService.startDebugging(config.launch); } catch (error) { diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index fd43be0439c..7634f82926d 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -671,7 +671,7 @@ export interface IConfigurationManager { name: string | undefined; }; - selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig): void; + selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig): Promise; getLaunches(): ReadonlyArray; @@ -692,7 +692,7 @@ export interface IConfigurationManager { isDebuggerInterestedInLanguage(language: string): boolean; hasDebugConfigurationProvider(debugType: string): boolean; - getDynamicProviders(): Promise<{ label: string, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[]>; + getDynamicProviders(): Promise<{ label: string, provider: IDebugConfigurationProvider, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[]>; registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable; unregisterDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): void; From 66db1a705700afb764217016cef129b7a210e8db Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 8 Sep 2020 10:07:21 +0200 Subject: [PATCH 49/98] #103454 remove objects.assign usage --- src/vs/base/parts/request/browser/request.ts | 6 ++-- .../common/extensionGalleryService.ts | 31 ++++++++++--------- .../node/extensionManagementService.ts | 9 ++++-- .../node/extensionsScanner.ts | 7 +++-- .../electron-main/requestMainService.ts | 3 +- .../platform/request/node/requestService.ts | 11 ++++--- .../common/userDataSyncStoreService.ts | 7 +++-- .../extensions/browser/extensionEditor.ts | 5 ++- .../extensionRecommendationsService.ts | 3 +- .../extensions/browser/extensionsViews.ts | 19 +++++++----- .../extensionRecommendationsService.test.ts | 8 ++--- .../extensionsActions.test.ts | 17 +++++----- .../electron-browser/extensionsViews.test.ts | 19 ++++++------ .../extensionsWorkbenchService.test.ts | 17 +++++----- .../extensionEnablementService.test.ts | 10 +++--- .../preferences/browser/preferencesService.ts | 5 ++- .../browser/api/extHostConfiguration.test.ts | 11 ++++--- 17 files changed, 97 insertions(+), 91 deletions(-) diff --git a/src/vs/base/parts/request/browser/request.ts b/src/vs/base/parts/request/browser/request.ts index 5dd4fdd449c..1c2499ba404 100644 --- a/src/vs/base/parts/request/browser/request.ts +++ b/src/vs/base/parts/request/browser/request.ts @@ -5,13 +5,15 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { canceled } from 'vs/base/common/errors'; -import { assign } from 'vs/base/common/objects'; import { VSBuffer, bufferToStream } from 'vs/base/common/buffer'; import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request'; export function request(options: IRequestOptions, token: CancellationToken): Promise { if (options.proxyAuthorization) { - options.headers = assign(options.headers || {}, { 'Proxy-Authorization': options.proxyAuthorization }); + options.headers = { + ...(options.headers || {}), + 'Proxy-Authorization': options.proxyAuthorization + }; } const xhr = new XMLHttpRequest(); diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 955557b345a..72975414203 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -6,7 +6,7 @@ import { getErrorMessage, isPromiseCanceledError, canceled } from 'vs/base/common/errors'; import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionIdentifier, IReportedExtension, InstallOperation, ITranslation, IGalleryExtensionVersion, IGalleryExtensionAssets, isIExtensionIdentifier, DefaultIconPath } from 'vs/platform/extensionManagement/common/extensionManagement'; import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { assign, getOrDefault } from 'vs/base/common/objects'; +import { getOrDefault } from 'vs/base/common/objects'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IPager } from 'vs/base/common/paging'; import { IRequestService, asJson, asText } from 'vs/platform/request/common/request'; @@ -158,7 +158,7 @@ class Query { get flags(): number { return this.state.flags; } withPage(pageNumber: number, pageSize: number = this.state.pageSize): Query { - return new Query(assign({}, this.state, { pageNumber, pageSize })); + return new Query({ ...this.state, pageNumber, pageSize }); } withFilter(filterType: FilterType, ...values: string[]): Query { @@ -167,23 +167,23 @@ class Query { ...values.length ? values.map(value => ({ filterType, value })) : [{ filterType }] ]; - return new Query(assign({}, this.state, { criteria })); + return new Query({ ...this.state, criteria }); } withSortBy(sortBy: SortBy): Query { - return new Query(assign({}, this.state, { sortBy })); + return new Query({ ...this.state, sortBy }); } withSortOrder(sortOrder: SortOrder): Query { - return new Query(assign({}, this.state, { sortOrder })); + return new Query({ ...this.state, sortOrder }); } withFlags(...flags: Flags[]): Query { - return new Query(assign({}, this.state, { flags: flags.reduce((r, f) => r | f, 0) })); + return new Query({ ...this.state, flags: flags.reduce((r, f) => r | f, 0) }); } withAssetTypes(...assetTypes: string[]): Query { - return new Query(assign({}, this.state, { assetTypes })); + return new Query({ ...this.state, assetTypes }); } get raw(): any { @@ -524,12 +524,13 @@ export class ExtensionGalleryService implements IExtensionGalleryService { } return this.commonHeadersPromise.then(commonHeaders => { const data = JSON.stringify(query.raw); - const headers = assign({}, commonHeaders, { + const headers = { + ...commonHeaders, 'Content-Type': 'application/json', 'Accept': 'application/json;api-version=3.0-preview.1', 'Accept-Encoding': 'gzip', - 'Content-Length': data.length - }); + 'Content-Length': String(data.length) + }; return this.requestService.request({ type: 'POST', @@ -585,7 +586,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { ] } */ - const log = (duration: number) => this.telemetryService.publicLog('galleryService:downloadVSIX', assign(data, { duration })); + const log = (duration: number) => this.telemetryService.publicLog('galleryService:downloadVSIX', { ...data, duration }); const operationParam = operation === InstallOperation.Install ? 'install' : operation === InstallOperation.Update ? 'update' : ''; const downloadAsset = operationParam ? { @@ -670,12 +671,12 @@ export class ExtensionGalleryService implements IExtensionGalleryService { private getAsset(asset: IGalleryExtensionAsset, options: IRequestOptions = {}, token: CancellationToken = CancellationToken.None): Promise { return this.commonHeadersPromise.then(commonHeaders => { const baseOptions = { type: 'GET' }; - const headers = assign({}, commonHeaders, options.headers || {}); - options = assign({}, options, baseOptions, { headers }); + const headers = { ...commonHeaders, ...(options.headers || {}) }; + options = { ...options, ...baseOptions, headers }; const url = asset.uri; const fallbackUrl = asset.fallbackUri; - const firstOptions = assign({}, options, { url }); + const firstOptions = { ...options, url }; return this.requestService.request(firstOptions, token) .then(context => { @@ -702,7 +703,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { }; this.telemetryService.publicLog2('galleryService:cdnFallback', { url, message }); - const fallbackOptions = assign({}, options, { url: fallbackUrl }); + const fallbackOptions = { ...options, url: fallbackUrl }; return this.requestService.request(fallbackOptions, token); }); }); diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index b26cf4129b2..9b0fd4db47e 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -6,7 +6,6 @@ import * as nls from 'vs/nls'; import * as path from 'vs/base/common/path'; import * as pfs from 'vs/base/node/pfs'; -import { assign } from 'vs/base/common/objects'; import { toDisposable, Disposable } from 'vs/base/common/lifecycle'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { zip, IFile } from 'vs/base/node/zip'; @@ -46,6 +45,7 @@ import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common import { ExtensionsDownloader } from 'vs/platform/extensionManagement/node/extensionDownloader'; import { ExtensionsScanner, IMetadata } from 'vs/platform/extensionManagement/node/extensionsScanner'; import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle'; +import { IStringDictionary } from 'vs/base/common/collections'; const INSTALL_ERROR_UNSET_UNINSTALLED = 'unsetUninstalled'; const INSTALL_ERROR_DOWNLOADING = 'downloading'; @@ -677,7 +677,10 @@ export class ExtensionManagementService extends Disposable implements IExtension private setUninstalled(...extensions: ILocalExtension[]): Promise<{ [id: string]: boolean }> { const ids: ExtensionIdentifierWithVersion[] = extensions.map(e => new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version)); - return this.extensionsScanner.withUninstalledExtensions(uninstalled => assign(uninstalled, ids.reduce((result, id) => { result[id.key()] = true; return result; }, {} as { [id: string]: boolean }))); + return this.extensionsScanner.withUninstalledExtensions(uninstalled => { + const newUninstalled = (ids.reduce>((result, id) => { result[id.key()] = true; return result; }, {})); + return { ...uninstalled, ...newUninstalled }; + }); } private unsetUninstalled(extensionIdentifier: ExtensionIdentifierWithVersion): Promise { @@ -745,6 +748,6 @@ export class ExtensionManagementService extends Disposable implements IExtension ] } */ - this.telemetryService.publicLogError(eventName, assign(extensionData, { success: !error, duration, errorcode })); + this.telemetryService.publicLogError(eventName, { ...extensionData, success: !error, duration, errorcode }); } } diff --git a/src/vs/platform/extensionManagement/node/extensionsScanner.ts b/src/vs/platform/extensionManagement/node/extensionsScanner.ts index ef3ba9f7ace..819dc9d2bd2 100644 --- a/src/vs/platform/extensionManagement/node/extensionsScanner.ts +++ b/src/vs/platform/extensionManagement/node/extensionsScanner.ts @@ -22,7 +22,7 @@ import { CancellationToken } from 'vscode'; import { extract, ExtractError } from 'vs/base/node/zip'; import { isWindows } from 'vs/base/common/platform'; import { flatten } from 'vs/base/common/arrays'; -import { assign } from 'vs/base/common/objects'; +import { IStringDictionary } from 'vs/base/common/collections'; const ERROR_SCANNING_SYS_EXTENSIONS = 'scanningSystem'; const ERROR_SCANNING_USER_EXTENSIONS = 'scanningUser'; @@ -31,6 +31,7 @@ const INSTALL_ERROR_DELETING = 'deleting'; const INSTALL_ERROR_RENAMING = 'renaming'; export type IMetadata = Partial; +type ILocalExtensionManifest = IExtensionManifest & { __metadata?: IMetadata }; export class ExtensionsScanner extends Disposable { @@ -133,7 +134,7 @@ export class ExtensionsScanner extends Disposable { const manifestPath = path.join(local.location.fsPath, 'package.json'); const raw = await pfs.readFile(manifestPath, 'utf8'); const { manifest } = await this.parseManifest(raw); - assign(manifest, { __metadata: metadata }); + (manifest as ILocalExtensionManifest).__metadata = metadata; await pfs.writeFile(manifestPath, JSON.stringify(manifest, null, '\t')); return local; } @@ -142,7 +143,7 @@ export class ExtensionsScanner extends Disposable { return this.withUninstalledExtensions(uninstalled => uninstalled); } - async withUninstalledExtensions(fn: (uninstalled: { [id: string]: boolean; }) => T): Promise { + async withUninstalledExtensions(fn: (uninstalled: IStringDictionary) => T): Promise { return this.uninstalledFileLimiter.queue(async () => { let result: T | null = null; return pfs.readFile(this.uninstalledPath, 'utf8') diff --git a/src/vs/platform/request/electron-main/requestMainService.ts b/src/vs/platform/request/electron-main/requestMainService.ts index 7f8b7141212..d08f82f4510 100644 --- a/src/vs/platform/request/electron-main/requestMainService.ts +++ b/src/vs/platform/request/electron-main/requestMainService.ts @@ -5,7 +5,6 @@ import { IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request'; import { RequestService as NodeRequestService, IRawRequestFunction } from 'vs/platform/request/node/requestService'; -import { assign } from 'vs/base/common/objects'; import { net } from 'electron'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -16,6 +15,6 @@ function getRawRequest(options: IRequestOptions): IRawRequestFunction { export class RequestMainService extends NodeRequestService { request(options: IRequestOptions, token: CancellationToken): Promise { - return super.request(assign({}, options || {}, { getRawRequest }), token); + return super.request({ ...(options || {}), getRawRequest }, token); } } diff --git a/src/vs/platform/request/node/requestService.ts b/src/vs/platform/request/node/requestService.ts index 377929d065d..41e23aea2f3 100644 --- a/src/vs/platform/request/node/requestService.ts +++ b/src/vs/platform/request/node/requestService.ts @@ -9,7 +9,6 @@ import * as streams from 'vs/base/common/stream'; import { createGunzip } from 'zlib'; import { parse as parseUrl } from 'url'; import { Disposable } from 'vs/base/common/lifecycle'; -import { assign } from 'vs/base/common/objects'; import { isBoolean, isNumber } from 'vs/base/common/types'; import { canceled } from 'vs/base/common/errors'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -67,7 +66,10 @@ export class RequestService extends Disposable implements IRequestService { options.strictSSL = strictSSL; if (this.authorization) { - options.headers = assign(options.headers || {}, { 'Proxy-Authorization': this.authorization }); + options.headers = { + ...(options.headers || {}), + 'Proxy-Authorization': this.authorization + }; } return this._request(options, token); @@ -107,10 +109,11 @@ export class RequestService extends Disposable implements IRequestService { req = rawRequest(opts, (res: http.IncomingMessage) => { const followRedirects: number = isNumber(options.followRedirects) ? options.followRedirects : 3; if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers['location']) { - this._request(assign({}, options, { + this._request({ + ...options, url: res.headers['location'], followRedirects: followRedirects - 1 - }), token).then(c, e); + }, token).then(c, e); } else { let stream: streams.ReadableStreamEvents = res; diff --git a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts index 0d9489ed8e9..a2cb34789eb 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncStoreService.ts @@ -15,7 +15,6 @@ import { getServiceMachineId } from 'vs/platform/serviceMachineId/common/service import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IFileService } from 'vs/platform/files/common/files'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { assign } from 'vs/base/common/objects'; import { generateUuid } from 'vs/base/common/uuid'; import { isWeb } from 'vs/base/common/platform'; import { Emitter, Event } from 'vs/base/common/event'; @@ -355,10 +354,12 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync this.setDonotMakeRequestsUntil(undefined); const commonHeaders = await this.commonHeadersPromise; - options.headers = assign(options.headers || {}, commonHeaders, { + options.headers = { + ...(options.headers || {}), + ...commonHeaders, 'X-Account-Type': this.authToken.type, 'authorization': `Bearer ${this.authToken.token}`, - }); + }; // Add session headers this.addSessionHeaders(options.headers); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index b0198b8aab4..d5783324492 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -37,7 +37,6 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { Color } from 'vs/base/common/color'; -import { assign } from 'vs/base/common/objects'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionsTree, ExtensionData, ExtensionsGridView, getExtensions } from 'vs/workbench/contrib/extensions/browser/extensionsViewer'; @@ -361,7 +360,7 @@ export class ExtensionEditor extends EditorPane { ] } */ - this.telemetryService.publicLog('extensionGallery:openExtension', assign(extension.telemetryData, recommendationsData)); + this.telemetryService.publicLog('extensionGallery:openExtension', { ...extension.telemetryData, ...recommendationsData }); toggleClass(template.name, 'clickable', !!extension.url); toggleClass(template.publisher, 'clickable', !!extension.url); @@ -556,7 +555,7 @@ export class ExtensionEditor extends EditorPane { ] } */ - this.telemetryService.publicLog('extensionEditor:navbarChange', assign(extension.telemetryData, { navItem: id })); + this.telemetryService.publicLog('extensionEditor:navbarChange', { ...extension.telemetryData, navItem: id }); } this.contentDisposables.clear(); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationsService.ts b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationsService.ts index dfc62721900..c3d8687c295 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationsService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationsService.ts @@ -13,7 +13,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { distinct, shuffle } from 'vs/base/common/arrays'; import { Emitter, Event } from 'vs/base/common/event'; -import { assign } from 'vs/base/common/objects'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { LifecyclePhase, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { DynamicWorkspaceRecommendations } from 'vs/workbench/contrib/extensions/browser/dynamicWorkspaceRecommendations'; @@ -260,7 +259,7 @@ export class ExtensionRecommendationsService extends Disposable implements IExte ] } */ - this.telemetryService.publicLog('extensionGallery:install:recommendations', assign(e.gallery.telemetryData, { recommendationReason: recommendationReason.reasonId })); + this.telemetryService.publicLog('extensionGallery:install:recommendations', { ...e.gallery.telemetryData, recommendationReason: recommendationReason.reasonId }); } } } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index becdf408944..2a5b085e0dd 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -5,7 +5,6 @@ import { localize } from 'vs/nls'; import { Disposable } from 'vs/base/common/lifecycle'; -import { assign } from 'vs/base/common/objects'; import { Event, Emitter } from 'vs/base/common/event'; import { isPromiseCanceledError, getErrorMessage } from 'vs/base/common/errors'; import { PagedModel, IPagedModel, IPager, DelayedPagedModel } from 'vs/base/common/paging'; @@ -198,10 +197,10 @@ export class ExtensionsListView extends ViewPane { }; switch (parsedQuery.sortBy) { - case 'installs': options = assign(options, { sortBy: SortBy.InstallCount }); break; - case 'rating': options = assign(options, { sortBy: SortBy.WeightedRating }); break; - case 'name': options = assign(options, { sortBy: SortBy.Title }); break; - case 'publishedDate': options = assign(options, { sortBy: SortBy.PublishedDate }); break; + case 'installs': options.sortBy = SortBy.InstallCount; break; + case 'rating': options.sortBy = SortBy.WeightedRating; break; + case 'name': options.sortBy = SortBy.Title; break; + case 'publishedDate': options.sortBy = SortBy.PublishedDate; break; } const successCallback = (model: IPagedModel) => { @@ -472,13 +471,15 @@ export class ExtensionsListView extends ViewPane { const text = query.value; if (/\bext:([^\s]+)\b/g.test(text)) { - options = assign(options, { text, source: 'file-extension-tags' }); + options.text = text; + options.source = 'file-extension-tags'; return this.extensionsWorkbenchService.queryGallery(options, token).then(pager => this.getPagedModel(pager)); } let preferredResults: string[] = []; if (text) { - options = assign(options, { text: text.substr(0, 350), source: 'searchText' }); + options.text = text.substr(0, 350); + options.source = 'searchText'; if (!hasUserDefinedSortOrder) { const searchExperiments = await this.getSearchExperiments(); for (const experiment of searchExperiments) { @@ -544,7 +545,9 @@ export class ExtensionsListView extends ViewPane { const names = await this.experimentService.getCuratedExtensionsList(value); if (Array.isArray(names) && names.length) { options.source = `curated:${value}`; - const pager = await this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }), token); + options.names = names; + options.pageSize = names.length; + const pager = await this.extensionsWorkbenchService.queryGallery(options, token); this.sortFirstPage(pager, names); return this.getPagedModel(pager || []); } 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 0ac3774a174..93146eae585 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 @@ -30,7 +30,6 @@ import { URI } from 'vs/base/common/uri'; import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { IPager } from 'vs/base/common/paging'; -import { assign } from 'vs/base/common/objects'; import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ConfigurationKey, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; @@ -166,10 +165,9 @@ const noAssets: IGalleryExtensionAssets = { }; function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: IGalleryExtensionAssets = noAssets): IGalleryExtension { - const galleryExtension = Object.create({}); - assign(galleryExtension, { name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {} }, properties); - assign(galleryExtension.properties, { dependencies: [] }, galleryExtensionProperties); - assign(galleryExtension.assets, assets); + const galleryExtension = Object.create({ name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {}, ...properties }); + galleryExtension.properties = { ...galleryExtension.properties, dependencies: [], ...galleryExtensionProperties }; + galleryExtension.assets = { ...galleryExtension.assets, ...assets }; galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: uuid.generateUuid() }; return galleryExtension; } 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 e2f71dede95..3f1897744af 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 @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { assign } from 'vs/base/common/objects'; import { generateUuid } from 'vs/base/common/uuid'; import { IExtensionsWorkbenchService, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions'; import * as ExtensionsActions from 'vs/workbench/contrib/extensions/browser/extensionsActions'; @@ -2494,20 +2493,20 @@ suite('LocalInstallAction', () => { }); function aLocalExtension(name: string = 'someext', manifest: any = {}, properties: any = {}): ILocalExtension { - manifest = assign({ name, publisher: 'pub', version: '1.0.0' }, manifest); - properties = assign({ + manifest = { name, publisher: 'pub', version: '1.0.0', ...manifest }; + properties = { type: ExtensionType.User, location: URI.file(`pub.${name}`), - identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name) } - }, properties); + identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name) }, + ...properties + }; return Object.create({ manifest, ...properties }); } function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: any = {}): IGalleryExtension { - const galleryExtension = Object.create({}); - assign(galleryExtension, { name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {} }, properties); - assign(galleryExtension.properties, { dependencies: [] }, galleryExtensionProperties); - assign(galleryExtension.assets, assets); + const galleryExtension = Object.create({ name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {}, ...properties }); + galleryExtension.properties = { ...galleryExtension.properties, dependencies: [], ...galleryExtensionProperties }; + galleryExtension.assets = { ...galleryExtension.assets, ...assets }; galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: generateUuid() }; return galleryExtension; } 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 e2a88db3452..7bcdce8cb9e 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 @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { assign } from 'vs/base/common/objects'; import { generateUuid } from 'vs/base/common/uuid'; import { ExtensionsListView } from 'vs/workbench/contrib/extensions/browser/extensionsViews'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; @@ -525,21 +524,21 @@ suite('ExtensionsListView Tests', () => { }); function aLocalExtension(name: string = 'someext', manifest: any = {}, properties: any = {}): ILocalExtension { - manifest = assign({ name, publisher: 'pub', version: '1.0.0' }, manifest); - properties = assign({ + manifest = { name, publisher: 'pub', version: '1.0.0', ...manifest }; + properties = { type: ExtensionType.User, location: URI.file(`pub.${name}`), - identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name), uuid: undefined }, - metadata: { id: getGalleryExtensionId(manifest.publisher, manifest.name), publisherId: manifest.publisher, publisherDisplayName: 'somename' } - }, properties); + identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name) }, + metadata: { id: getGalleryExtensionId(manifest.publisher, manifest.name), publisherId: manifest.publisher, publisherDisplayName: 'somename' }, + ...properties + }; return Object.create({ manifest, ...properties }); } function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: any = {}): IGalleryExtension { - const galleryExtension = Object.create({}); - assign(galleryExtension, { name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {} }, properties); - assign(galleryExtension.properties, { dependencies: [] }, galleryExtensionProperties); - assign(galleryExtension.assets, assets); + const galleryExtension = Object.create({ name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {}, ...properties }); + galleryExtension.properties = { ...galleryExtension.properties, dependencies: [], ...galleryExtensionProperties }; + galleryExtension.assets = { ...galleryExtension.assets, ...assets }; galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: generateUuid() }; return galleryExtension; } 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 b7f98de6930..15c3f1a0241 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 @@ -6,7 +6,6 @@ import * as sinon from 'sinon'; import * as assert from 'assert'; import * as fs from 'fs'; -import { assign } from 'vs/base/common/objects'; import { generateUuid } from 'vs/base/common/uuid'; import { IExtensionsWorkbenchService, ExtensionState, AutoCheckUpdatesConfigurationKey, AutoUpdateConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions'; import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService'; @@ -1368,12 +1367,13 @@ suite('ExtensionsWorkbenchServiceTest', () => { } function aLocalExtension(name: string = 'someext', manifest: any = {}, properties: any = {}): ILocalExtension { - manifest = assign({ name, publisher: 'pub', version: '1.0.0' }, manifest); - properties = assign({ + manifest = { name, publisher: 'pub', version: '1.0.0', ...manifest }; + properties = { type: ExtensionType.User, location: URI.file(`pub.${name}`), - identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name) } - }, properties); + identifier: { id: getGalleryExtensionId(manifest.publisher, manifest.name) }, + ...properties + }; return Object.create({ manifest, ...properties }); } @@ -1389,10 +1389,9 @@ suite('ExtensionsWorkbenchServiceTest', () => { }; function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: IGalleryExtensionAssets = noAssets): IGalleryExtension { - const galleryExtension = Object.create({}); - assign(galleryExtension, { name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {} }, properties); - assign(galleryExtension.properties, { dependencies: [] }, galleryExtensionProperties); - assign(galleryExtension.assets, assets); + const galleryExtension = Object.create({ name, publisher: 'pub', version: '1.0.0', properties: {}, assets: {}, ...properties }); + galleryExtension.properties = { ...galleryExtension.properties, dependencies: [], ...galleryExtensionProperties }; + galleryExtension.assets = { ...galleryExtension.assets, ...assets }; galleryExtension.identifier = { id: getGalleryExtensionId(galleryExtension.publisher, galleryExtension.name), uuid: generateUuid() }; return galleryExtension; } diff --git a/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts b/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts index 79ba1b68a98..02ddb58cf37 100644 --- a/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts +++ b/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts @@ -19,7 +19,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts'; -import { assign } from 'vs/base/common/objects'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { productService } from 'vs/workbench/test/browser/workbenchTestServices'; import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService'; @@ -608,11 +607,12 @@ function aLocalExtension(id: string, contributes?: IExtensionContributions, type function aLocalExtension2(id: string, manifest: any = {}, properties: any = {}): ILocalExtension { const [publisher, name] = id.split('.'); - properties = assign({ + manifest = { name, publisher, ...manifest }; + properties = { identifier: { id }, galleryIdentifier: { id, uuid: undefined }, - type: ExtensionType.User - }, properties); - manifest = assign({ name, publisher }, manifest); + type: ExtensionType.User, + ...properties + }; return Object.create({ manifest, ...properties }); } diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index e6a180a5c3e..7af8b182127 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -7,7 +7,6 @@ import { Emitter } from 'vs/base/common/event'; import { parse } from 'vs/base/common/json'; import { Disposable } from 'vs/base/common/lifecycle'; import * as network from 'vs/base/common/network'; -import { assign } from 'vs/base/common/objects'; import { URI } from 'vs/base/common/uri'; import { getCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IPosition } from 'vs/editor/common/core/position'; @@ -346,7 +345,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic if (!options) { options = { pinned: true }; } else { - options = assign(options, { pinned: true }); + options = { ...options, pinned: true }; } if (openDefaultSettings) { @@ -368,7 +367,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic if (!options) { options = { pinned: true }; } else { - options = assign(options, { pinned: true }); + options = { ...options, pinned: true }; } const defaultPreferencesEditorInput = this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.getDefaultSettingsResource(configurationTarget)); diff --git a/src/vs/workbench/test/browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/browser/api/extHostConfiguration.test.ts index a442a594c50..470a1db5e6d 100644 --- a/src/vs/workbench/test/browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/browser/api/extHostConfiguration.test.ts @@ -14,7 +14,6 @@ import { mock } from 'vs/base/test/common/mock'; import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { ConfigurationTarget, IConfigurationModel, IConfigurationChange } from 'vs/platform/configuration/common/configuration'; import { NullLogService } from 'vs/platform/log/common/log'; -import { assign } from 'vs/base/common/objects'; import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; suite('ExtHostConfiguration', function () { @@ -211,20 +210,22 @@ suite('ExtHostConfiguration', function () { }), JSON.stringify(actual)); actual = all.getConfiguration('workbench').get('emptyobjectkey'); - actual = assign(actual || {}, { + actual = { + ...(actual || {}), 'statusBar.background': `#0ff`, 'statusBar.foreground': `#ff0`, - }); + }; assert.deepEqual(JSON.stringify({ 'statusBar.background': `#0ff`, 'statusBar.foreground': `#ff0`, }), JSON.stringify(actual)); actual = all.getConfiguration('workbench').get('unknownkey'); - actual = assign(actual || {}, { + actual = { + ...(actual || {}), 'statusBar.background': `#0ff`, 'statusBar.foreground': `#ff0`, - }); + }; assert.deepEqual(JSON.stringify({ 'statusBar.background': `#0ff`, 'statusBar.foreground': `#ff0`, From 175730751395dbb5526c89413ea7d29df74cdf3e Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 8 Sep 2020 11:01:43 +0200 Subject: [PATCH 50/98] #103454 do not use deprecated methods --- .../contrib/gotoError/gotoErrorWidget.ts | 12 +++++----- .../editor/contrib/hover/modesContentHover.ts | 4 ++-- .../parts/activitybar/activitybarPart.ts | 16 ++++++------- .../workbench/browser/parts/compositeBar.ts | 6 ++--- .../browser/parts/compositeBarActions.ts | 22 ++++++++--------- .../workbench/browser/parts/compositePart.ts | 4 ++-- .../browser/parts/editor/sideBySideEditor.ts | 2 +- .../browser/parts/panel/panelPart.ts | 8 +++---- .../browser/parts/views/viewPaneContainer.ts | 24 +++++++++---------- .../extensions/browser/extensionEditor.ts | 20 ++++++++-------- .../extensions/browser/extensionsList.ts | 8 +++---- .../extensions/browser/extensionsViewer.ts | 2 +- .../extensions/browser/extensionsViewlet.ts | 6 ++--- .../extensions/browser/extensionsViews.ts | 8 +++---- .../extensions/browser/extensionsWidgets.ts | 10 ++++---- .../runtimeExtensionsEditor.ts | 6 ++--- .../markers/browser/markersTreeViewer.ts | 6 ++--- .../contrib/markers/browser/markersView.ts | 10 ++++---- .../markers/browser/markersViewActions.ts | 10 ++++---- .../contrib/output/browser/outputView.ts | 5 ++-- .../preferences/browser/keybindingsEditor.ts | 24 +++++++++---------- .../preferences/browser/preferencesEditor.ts | 4 ++-- .../preferences/browser/preferencesWidgets.ts | 22 ++++++++--------- 23 files changed, 119 insertions(+), 120 deletions(-) diff --git a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts index f5b6ec41d4f..66bdc31f06c 100644 --- a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts +++ b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts @@ -57,7 +57,7 @@ class MessageWidget { domNode.className = 'descriptioncontainer'; this._messageBlock = document.createElement('div'); - dom.addClass(this._messageBlock, 'message'); + this._messageBlock.classList.add('message'); this._messageBlock.setAttribute('aria-live', 'assertive'); this._messageBlock.setAttribute('role', 'alert'); domNode.appendChild(this._messageBlock); @@ -123,19 +123,19 @@ class MessageWidget { } if (source || code) { const detailsElement = document.createElement('span'); - dom.addClass(detailsElement, 'details'); + detailsElement.classList.add('details'); lastLineElement.appendChild(detailsElement); if (source) { const sourceElement = document.createElement('span'); sourceElement.innerText = source; - dom.addClass(sourceElement, 'source'); + sourceElement.classList.add('source'); detailsElement.appendChild(sourceElement); } if (code) { if (typeof code === 'string') { const codeElement = document.createElement('span'); codeElement.innerText = `(${code})`; - dom.addClass(codeElement, 'code'); + codeElement.classList.add('code'); detailsElement.appendChild(codeElement); } else { this._codeLink = dom.$('a.code-link'); @@ -166,7 +166,7 @@ class MessageWidget { let container = document.createElement('div'); let relatedResource = document.createElement('a'); - dom.addClass(relatedResource, 'filename'); + relatedResource.classList.add('filename'); relatedResource.innerText = `${getBaseLabel(related.resource)}(${related.startLineNumber}, ${related.startColumn}): `; relatedResource.title = getPathLabel(related.resource, undefined); this._relatedDiagnostics.set(relatedResource, related); @@ -318,7 +318,7 @@ export class MarkerNavigationWidget extends PeekViewWidget { protected _fillBody(container: HTMLElement): void { this._parentContainer = container; - dom.addClass(container, 'marker-widget'); + container.classList.add('marker-widget'); this._parentContainer.tabIndex = 0; this._parentContainer.setAttribute('role', 'tooltip'); diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 1d7fb929b81..46cb4d7a542 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -240,11 +240,11 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this._register(dom.addStandardDisposableListener(this.getDomNode(), dom.EventType.FOCUS, () => { if (this._colorPicker) { - dom.addClass(this.getDomNode(), 'colorpicker-hover'); + this.getDomNode().classList.add('colorpicker-hover'); } })); this._register(dom.addStandardDisposableListener(this.getDomNode(), dom.EventType.BLUR, () => { - dom.removeClass(this.getDomNode(), 'colorpicker-hover'); + this.getDomNode().classList.remove('colorpicker-hover'); })); this._register(editor.onDidChangeConfiguration((e) => { this._hoverOperation.setHoverTime(this._editor.getOption(EditorOption.hover).delay); diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 0045a91e2a6..14469f93bed 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -18,7 +18,7 @@ import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeServic import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BORDER } from 'vs/workbench/common/theme'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar'; -import { Dimension, addClass, removeNode, createCSSRule, asCSSUrl, toggleClass, addDisposableListener, EventType } from 'vs/base/browser/dom'; +import { Dimension, createCSSRule, asCSSUrl, addDisposableListener, EventType } from 'vs/base/browser/dom'; import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { URI, UriComponents } from 'vs/base/common/uri'; @@ -404,7 +404,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } if (this.menuBarContainer) { - removeNode(this.menuBarContainer); + this.menuBarContainer.remove(); this.menuBarContainer = undefined; this.registerKeyboardNavigationListeners(); } @@ -412,7 +412,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { private installMenubar() { this.menuBarContainer = document.createElement('div'); - addClass(this.menuBarContainer, 'menubar'); + this.menuBarContainer.classList.add('menubar'); const content = assertIsDefined(this.content); content.prepend(this.menuBarContainer); @@ -428,7 +428,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.element = parent; this.content = document.createElement('div'); - addClass(this.content, 'content'); + this.content.classList.add('content'); parent.appendChild(this.content); // Home action bar @@ -454,7 +454,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Global action bar this.globalActivitiesContainer = document.createElement('div'); - addClass(this.globalActivitiesContainer, 'global-activity'); + this.globalActivitiesContainer.classList.add('global-activity'); this.content.appendChild(this.globalActivitiesContainer); this.createGlobalActivityActionBar(this.globalActivitiesContainer); @@ -535,7 +535,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { this.homeBarContainer = document.createElement('div'); this.homeBarContainer.setAttribute('aria-label', nls.localize('homeIndicator', "Home")); this.homeBarContainer.setAttribute('role', 'toolbar'); - addClass(this.homeBarContainer, 'home-bar'); + this.homeBarContainer.classList.add('home-bar'); this.homeBar = this._register(new ActionBar(this.homeBarContainer, { orientation: ActionsOrientation.VERTICAL, @@ -547,7 +547,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { })); const homeBarIconBadge = document.createElement('div'); - addClass(homeBarIconBadge, 'home-bar-icon-badge'); + homeBarIconBadge.classList.add('home-bar-icon-badge'); this.homeBarContainer.appendChild(homeBarIconBadge); this.homeBar.push(this._register(this.instantiationService.createInstance(HomeAction, href, title, icon))); @@ -563,7 +563,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { container.style.backgroundColor = background; const borderColor = this.getColor(ACTIVITY_BAR_BORDER) || this.getColor(contrastBorder) || ''; - toggleClass(container, 'bordered', !!borderColor); + container.classList.toggle('bordered', !!borderColor); container.style.borderColor = borderColor ? borderColor : ''; } diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index f029a2c190c..4a674fc637a 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -12,7 +12,7 @@ import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar'; import { CompositeActionViewItem, CompositeOverflowActivityAction, ICompositeActivity, CompositeOverflowActivityActionViewItem, ActivityAction, ICompositeBar, ICompositeBarColors } from 'vs/workbench/browser/parts/compositeBarActions'; -import { Dimension, $, addDisposableListener, EventType, EventHelper, toggleClass, isAncestor } from 'vs/base/browser/dom'; +import { Dimension, $, addDisposableListener, EventType, EventHelper, isAncestor } from 'vs/base/browser/dom'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Widget } from 'vs/base/browser/ui/widget'; @@ -285,8 +285,8 @@ export class CompositeBar extends Widget implements ICompositeBar { } private updateFromDragging(element: HTMLElement, showFeedback: boolean, front: boolean): Before2D | undefined { - toggleClass(element, 'dragged-over-head', showFeedback && front); - toggleClass(element, 'dragged-over-tail', showFeedback && !front); + element.classList.toggle('dragged-over-head', showFeedback && front); + element.classList.toggle('dragged-over-tail', showFeedback && !front); if (!showFeedback) { return undefined; diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 9f358b6e25d..ac10772a1d9 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -205,7 +205,7 @@ export class ActivityActionViewItem extends BaseActionViewItem { // Try hard to prevent keyboard only focus feedback when using mouse this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_DOWN, () => { - dom.addClass(this.container, 'clicked'); + this.container.classList.add('clicked'); })); this._register(dom.addDisposableListener(this.container, dom.EventType.MOUSE_UP, () => { @@ -214,7 +214,7 @@ export class ActivityActionViewItem extends BaseActionViewItem { } this.mouseUpTimeout = setTimeout(() => { - dom.removeClass(this.container, 'clicked'); + this.container.classList.remove('clicked'); }, 800); // delayed to prevent focus feedback from showing on mouse up })); @@ -328,7 +328,7 @@ export class ActivityActionViewItem extends BaseActionViewItem { if (this.options.icon && !this.activity.iconUrl) { // Only apply codicon class to activity bar icon items without iconUrl - dom.addClass(this.label, 'codicon'); + this.label.classList.add('codicon'); } if (!this.options.icon) { @@ -588,10 +588,10 @@ export class CompositeActionViewItem extends ActivityActionViewItem { const left = forceLeft || (preferLeft && !lastClasses.horizontal) || (!forceRight && lastClasses.horizontal === 'left'); const right = forceRight || (!preferLeft && !lastClasses.horizontal) || (!forceLeft && lastClasses.horizontal === 'right'); - dom.toggleClass(element, 'top', showFeedback && top); - dom.toggleClass(element, 'bottom', showFeedback && bottom); - dom.toggleClass(element, 'left', showFeedback && left); - dom.toggleClass(element, 'right', showFeedback && right); + element.classList.toggle('top', showFeedback && top); + element.classList.toggle('bottom', showFeedback && bottom); + element.classList.toggle('left', showFeedback && left); + element.classList.toggle('right', showFeedback && right); if (!showFeedback) { return undefined; @@ -646,11 +646,11 @@ export class CompositeActionViewItem extends ActivityActionViewItem { protected updateChecked(): void { if (this.getAction().checked) { - dom.addClass(this.container, 'checked'); + this.container.classList.add('checked'); this.container.setAttribute('aria-label', nls.localize('compositeActive', "{0} active", this.container.title)); this.container.setAttribute('aria-expanded', 'true'); } else { - dom.removeClass(this.container, 'checked'); + this.container.classList.remove('checked'); this.container.setAttribute('aria-label', this.container.title); this.container.setAttribute('aria-expanded', 'false'); } @@ -663,9 +663,9 @@ export class CompositeActionViewItem extends ActivityActionViewItem { } if (this.getAction().enabled) { - dom.removeClass(this.element, 'disabled'); + this.element.classList.remove('disabled'); } else { - dom.addClass(this.element, 'disabled'); + this.element.classList.add('disabled'); } } diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index b3c94885b7a..6f13c837218 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -29,7 +29,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { Dimension, append, $, addClass, hide, show, addClasses } from 'vs/base/browser/dom'; +import { Dimension, append, $, hide, show, addClasses } from 'vs/base/browser/dom'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; @@ -384,7 +384,7 @@ export abstract class CompositePart extends Part { // Title Area Container const titleArea = append(parent, $('.composite')); - addClass(titleArea, 'title'); + titleArea.classList.add('title'); // Left Title Label this.titleLabel = this.createTitleLabel(titleArea); diff --git a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts index ed99e7e0567..bfbb9589777 100644 --- a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts +++ b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts @@ -68,7 +68,7 @@ export class SideBySideEditor extends EditorPane { } protected createEditor(parent: HTMLElement): void { - DOM.addClass(parent, 'side-by-side-editor'); + parent.classList.add('side-by-side-editor'); const splitview = this.splitview = this._register(new SplitView(parent, { orientation: Orientation.HORIZONTAL })); this._register(this.splitview.onDidSashReset(() => splitview.distributeViewSizes())); diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 84420014b15..e7480b64cec 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -26,7 +26,7 @@ import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbe import { ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions'; import { IBadge } from 'vs/workbench/services/activity/common/activity'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { Dimension, trackFocus, addClass, toggleClass, EventHelper } from 'vs/base/browser/dom'; +import { Dimension, trackFocus, EventHelper } from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -422,10 +422,10 @@ export class PanelPart extends CompositePart implements IPanelService { private createEmptyPanelMessage(): void { const contentArea = this.getContentArea()!; this.emptyPanelMessageElement = document.createElement('div'); - addClass(this.emptyPanelMessageElement, 'empty-panel-message-area'); + this.emptyPanelMessageElement.classList.add('empty-panel-message-area'); const messageElement = document.createElement('div'); - addClass(messageElement, 'empty-panel-message'); + messageElement.classList.add('empty-panel-message'); messageElement.innerText = localize('panel.emptyMessage', "Drag a view into the panel to display."); this.emptyPanelMessageElement.appendChild(messageElement); @@ -613,7 +613,7 @@ export class PanelPart extends CompositePart implements IPanelService { private emptyPanelMessageElement: HTMLElement | undefined; private layoutEmptyMessage(): void { if (this.emptyPanelMessageElement) { - toggleClass(this.emptyPanelMessageElement, 'visible', this.compositeBar.getVisibleComposites().length === 0); + this.emptyPanelMessageElement.classList.toggle('visible', this.compositeBar.getVisibleComposites().length === 0); } } diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 4f683146121..07c156043db 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { ColorIdentifier, activeContrastBorder, foreground } from 'vs/platform/theme/common/colorRegistry'; import { attachStyler, IColorMapping, attachButtonStyler, attachLinkStyler, attachProgressBarStyler } from 'vs/platform/theme/common/styler'; import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, PANEL_BACKGROUND, SIDE_BAR_BACKGROUND, PANEL_SECTION_HEADER_FOREGROUND, PANEL_SECTION_HEADER_BACKGROUND, PANEL_SECTION_HEADER_BORDER, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_SECTION_BORDER } from 'vs/workbench/common/theme'; -import { after, append, $, trackFocus, toggleClass, EventType, isAncestor, Dimension, addDisposableListener, removeClass, addClass, createCSSRule, asCSSUrl, addClasses } from 'vs/base/browser/dom'; +import { after, append, $, trackFocus, EventType, isAncestor, Dimension, addDisposableListener, createCSSRule, asCSSUrl, addClasses } from 'vs/base/browser/dom'; import { IDisposable, combinedDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IAction, Separator, IActionViewItem } from 'vs/base/common/actions'; import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -237,7 +237,7 @@ export abstract class ViewPane extends Pane implements IView { set headerVisible(visible: boolean) { super.headerVisible = visible; - toggleClass(this.element, 'merged-header', !visible); + this.element.classList.toggle('merged-header', !visible); } setVisible(visible: boolean): void { @@ -293,7 +293,7 @@ export abstract class ViewPane extends Pane implements IView { this.renderHeaderTitle(container, this.title); const actions = append(container, $('.actions')); - toggleClass(actions, 'show', this.showActionsAlways); + actions.classList.toggle('show', this.showActionsAlways); this.toolbar = new ToolBar(actions, this.contextMenuService, { orientation: ActionsOrientation.HORIZONTAL, actionViewItemProvider: action => this.getActionViewItem(action), @@ -356,7 +356,7 @@ export abstract class ViewPane extends Pane implements IView { -webkit-mask-size: 16px; `); } else if (isString(icon)) { - addClass(this.iconContainer, 'codicon'); + this.iconContainer.classList.add('codicon'); cssClass = icon; } @@ -488,7 +488,7 @@ export abstract class ViewPane extends Pane implements IView { return; } const shouldAlwaysShowActions = this.configurationService.getValue('workbench.view.alwaysShowHeaderActions'); - toggleClass(this.headerContainer, 'actions-always-visible', shouldAlwaysShowActions); + this.headerContainer.classList.toggle('actions-always-visible', shouldAlwaysShowActions); } protected updateActions(): void { @@ -533,7 +533,7 @@ export abstract class ViewPane extends Pane implements IView { this.viewWelcomeDisposable.dispose(); if (!this.shouldShowWelcome()) { - removeClass(this.bodyContainer, 'welcome'); + this.bodyContainer.classList.remove('welcome'); this.viewWelcomeContainer.innerText = ''; this.scrollableElement.scanDomNode(); return; @@ -542,14 +542,14 @@ export abstract class ViewPane extends Pane implements IView { const contents = this.viewWelcomeController.contents; if (contents.length === 0) { - removeClass(this.bodyContainer, 'welcome'); + this.bodyContainer.classList.remove('welcome'); this.viewWelcomeContainer.innerText = ''; this.scrollableElement.scanDomNode(); return; } const disposables = new DisposableStore(); - addClass(this.bodyContainer, 'welcome'); + this.bodyContainer.classList.add('welcome'); this.viewWelcomeContainer.innerText = ''; let buttonIndex = 0; @@ -679,15 +679,15 @@ class ViewPaneDropOverlay extends Themable { // Parent this.paneElement.appendChild(this.container); - addClass(this.paneElement, 'dragged-over'); + this.paneElement.classList.add('dragged-over'); this._register(toDisposable(() => { this.paneElement.removeChild(this.container); - removeClass(this.paneElement, 'dragged-over'); + this.paneElement.classList.remove('dragged-over'); })); // Overlay this.overlay = document.createElement('div'); - addClass(this.overlay, 'pane-overlay-indicator'); + this.overlay.classList.add('pane-overlay-indicator'); this.container.appendChild(this.overlay); // Overlay Event Handling @@ -818,7 +818,7 @@ class ViewPaneDropOverlay extends Themable { this.overlay.style.opacity = '1'; // Enable transition after a timeout to prevent initial animation - setTimeout(() => addClass(this.overlay, 'overlay-move-transition'), 0); + setTimeout(() => this.overlay.classList.add('overlay-move-transition'), 0); // Remember as current split direction this._currentDropOperation = dropDirection; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index d5783324492..5f73348ed0b 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -14,7 +14,7 @@ import { Action, IAction } from 'vs/base/common/actions'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { dispose, toDisposable, Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { domEvent } from 'vs/base/browser/event'; -import { append, $, addClass, removeClass, finalHandler, join, toggleClass, hide, show, addDisposableListener, EventType } from 'vs/base/browser/dom'; +import { append, $, finalHandler, join, hide, show, addDisposableListener, EventType } from 'vs/base/browser/dom'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -362,9 +362,9 @@ export class ExtensionEditor extends EditorPane { */ this.telemetryService.publicLog('extensionGallery:openExtension', { ...extension.telemetryData, ...recommendationsData }); - toggleClass(template.name, 'clickable', !!extension.url); - toggleClass(template.publisher, 'clickable', !!extension.url); - toggleClass(template.rating, 'clickable', !!extension.url); + template.name.classList.toggle('clickable', !!extension.url); + template.publisher.classList.toggle('clickable', !!extension.url); + template.rating.classList.toggle('clickable', !!extension.url); if (extension.url) { this.transientDisposables.add(this.onClick(template.name, () => this.openerService.open(URI.parse(extension.url!)))); this.transientDisposables.add(this.onClick(template.rating, () => this.openerService.open(URI.parse(`${extension.url}#review-details`)))); @@ -847,13 +847,13 @@ export class ExtensionEditor extends EditorPane { const extensionPack = append(extensionPackReadme, $('div', { class: 'extension-pack' })); if (manifest.extensionPack!.length <= 3) { - addClass(extensionPackReadme, 'one-row'); + extensionPackReadme.classList.add('one-row'); } else if (manifest.extensionPack!.length <= 6) { - addClass(extensionPackReadme, 'two-rows'); + extensionPackReadme.classList.add('two-rows'); } else if (manifest.extensionPack!.length <= 9) { - addClass(extensionPackReadme, 'three-rows'); + extensionPackReadme.classList.add('three-rows'); } else { - addClass(extensionPackReadme, 'more-rows'); + extensionPackReadme.classList.add('more-rows'); } const extensionPackHeader = append(extensionPack, $('div.header')); @@ -1436,10 +1436,10 @@ export class ExtensionEditor extends EditorPane { } private loadContents(loadingTask: () => CacheResult, template: IExtensionEditorTemplate): Promise { - addClass(template.content, 'loading'); + template.content.classList.add('loading'); const result = this.contentDisposables.add(loadingTask()); - const onDone = () => removeClass(template.content, 'loading'); + const onDone = () => template.content.classList.remove('loading'); result.promise.then(onDone, onDone); return result.promise; diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts index 975786bc6f6..21e9118f568 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/extension'; -import { append, $, addClass, removeClass, toggleClass } from 'vs/base/browser/dom'; +import { append, $ } from 'vs/base/browser/dom'; import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; import { IAction } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -135,7 +135,7 @@ export class Renderer implements IPagedRenderer { } renderPlaceholder(index: number, data: ITemplateData): void { - addClass(data.element, 'loading'); + data.element.classList.add('loading'); data.root.removeAttribute('aria-label'); data.root.removeAttribute('data-extension-id'); @@ -150,7 +150,7 @@ export class Renderer implements IPagedRenderer { } renderElement(extension: IExtension, index: number, data: ITemplateData): void { - removeClass(data.element, 'loading'); + data.element.classList.remove('loading'); data.root.setAttribute('data-extension-id', extension.identifier.id); if (extension.state !== ExtensionState.Uninstalled && !extension.server) { @@ -168,7 +168,7 @@ export class Renderer implements IPagedRenderer { const runningExtension = runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, extension.identifier))[0]; isDisabled = !(runningExtension && extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension))); } - toggleClass(data.root, 'disabled', isDisabled); + data.root.classList.toggle('disabled', isDisabled); }; updateEnablement(); this.extensionService.onDidChangeExtensions(() => updateEnablement(), this, data.extensionDisposables); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts index 5ee60dcc409..d6436bc993f 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts @@ -136,7 +136,7 @@ export class ExtensionRenderer implements IListRenderer('img.icon')); const details = dom.append(container, dom.$('.details')); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index a5221aff5e8..a03702b05d0 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -13,7 +13,7 @@ import { Event as EventOf, Emitter } from 'vs/base/common/event'; import { IAction, Action, Separator, SubmenuAction } from 'vs/base/common/actions'; import { IViewlet } from 'vs/workbench/common/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; -import { append, $, addClass, toggleClass, Dimension, hide, show } from 'vs/base/browser/dom'; +import { append, $, Dimension, hide, show } from 'vs/base/browser/dom'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -404,7 +404,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE } create(parent: HTMLElement): void { - addClass(parent, 'extensions-viewlet'); + parent.classList.add('extensions-viewlet'); this.root = parent; const overlay = append(this.root, $('.overlay')); @@ -500,7 +500,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE layout(dimension: Dimension): void { if (this.root) { - toggleClass(this.root, 'narrow', dimension.width <= 300); + this.root.classList.toggle('narrow', dimension.width <= 300); } if (this.searchBox) { this.searchBox.layout({ height: 20, width: dimension.width - 34 }); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index 2a5b085e0dd..2cc1ddbebc0 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -13,7 +13,7 @@ import { IExtensionManagementServer, IExtensionManagementServerService, IExtensi import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { append, $, toggleClass, addClass } from 'vs/base/browser/dom'; +import { append, $ } from 'vs/base/browser/dom'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Delegate, Renderer, IExtensionsViewState } from 'vs/workbench/contrib/extensions/browser/extensionsList'; import { IExtension, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; @@ -120,7 +120,7 @@ export class ExtensionsListView extends ViewPane { } protected renderHeader(container: HTMLElement): void { - addClass(container, 'extension-view-header'); + container.classList.add('extension-view-header'); super.renderHeader(container); this.badge = new CountBadge(append(container, $('.count-badge-wrapper'))); @@ -704,8 +704,8 @@ export class ExtensionsListView extends ViewPane { if (this.bodyTemplate && this.badge) { - toggleClass(this.bodyTemplate.extensionsList, 'hidden', count === 0); - toggleClass(this.bodyTemplate.messageContainer, 'hidden', count > 0); + this.bodyTemplate.extensionsList.classList.toggle('hidden', count === 0); + this.bodyTemplate.messageContainer.classList.toggle('hidden', count > 0); this.badge.setCount(count); if (count === 0 && this.isBodyVisible()) { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts index c5758eac3d6..63fcc8f02b2 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/extensionsWidgets'; import { Disposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { IExtension, IExtensionsWorkbenchService, IExtensionContainer } from 'vs/workbench/contrib/extensions/common/extensions'; -import { append, $, addClass, removeNode } from 'vs/base/browser/dom'; +import { append, $ } from 'vs/base/browser/dom'; import * as platform from 'vs/base/common/platform'; import { localize } from 'vs/nls'; import { IExtensionRecommendationsService, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; @@ -50,7 +50,7 @@ export class InstallCountWidget extends ExtensionWidget { @IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService ) { super(); - addClass(container, 'extension-install-count'); + container.classList.add('extension-install-count'); this.render(); } @@ -95,10 +95,10 @@ export class RatingsWidget extends ExtensionWidget { private small: boolean ) { super(); - addClass(container, 'extension-ratings'); + container.classList.add('extension-ratings'); if (this.small) { - addClass(container, 'small'); + container.classList.add('small'); } this.render(); @@ -325,7 +325,7 @@ export class ExtensionPackCountWidget extends ExtensionWidget { private clear(): void { if (this.element) { - removeNode(this.element); + this.element.remove(); } } diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 56276cdec45..d34cf3bdd8a 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -17,7 +17,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IExtensionService, IExtensionsStatus, IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions'; import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/list'; import { WorkbenchList } from 'vs/platform/list/browser/listService'; -import { append, $, reset, addClass, toggleClass, Dimension, clearNode } from 'vs/base/browser/dom'; +import { append, $, reset, Dimension, clearNode } from 'vs/base/browser/dom'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { RunOnceScheduler } from 'vs/base/common/async'; @@ -257,7 +257,7 @@ export class RuntimeExtensionsEditor extends EditorPane { } protected createEditor(parent: HTMLElement): void { - addClass(parent, 'runtime-extensions-editor'); + parent.classList.add('runtime-extensions-editor'); const TEMPLATE_ID = 'runtimeExtensionElementTemplate'; @@ -328,7 +328,7 @@ export class RuntimeExtensionsEditor extends EditorPane { data.elementDisposables = dispose(data.elementDisposables); - toggleClass(data.root, 'odd', index % 2 === 1); + data.root.classList.toggle('odd', index % 2 === 1); const onError = Event.once(domEvent(data.icon, 'error')); onError(() => data.icon.src = element.marketplaceInfo.iconUrlFallback, null, data.elementDisposables); diff --git a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts index 45c6e3f2145..c1f4dd65b2f 100644 --- a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts +++ b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts @@ -346,10 +346,10 @@ class MarkerWidget extends Disposable { if (viewModel) { const quickFixAction = viewModel.quickFixAction; this.actionBar.push([quickFixAction], { icon: true, label: false }); - dom.toggleClass(this.icon, 'quickFix', quickFixAction.enabled); + this.icon.classList.toggle('quickFix', quickFixAction.enabled); quickFixAction.onDidChange(({ enabled }) => { if (!isUndefinedOrNull(enabled)) { - dom.toggleClass(this.icon, 'quickFix', enabled); + this.icon.classList.toggle('quickFix', enabled); } }, this, this.disposables); quickFixAction.onShowQuickFixes(() => { @@ -393,7 +393,7 @@ class MarkerWidget extends Disposable { } private renderDetails(marker: IMarker, filterData: MarkerFilterData | undefined, parent: HTMLElement): void { - dom.addClass(parent, 'details-container'); + parent.classList.add('details-container'); if (marker.source || marker.code) { const source = new HighlightedLabel(dom.append(parent, dom.$('.marker-source')), false); diff --git a/src/vs/workbench/contrib/markers/browser/markersView.ts b/src/vs/workbench/contrib/markers/browser/markersView.ts index 528a7beeffc..2163578c6d3 100644 --- a/src/vs/workbench/contrib/markers/browser/markersView.ts +++ b/src/vs/workbench/contrib/markers/browser/markersView.ts @@ -144,7 +144,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { public renderBody(parent: HTMLElement): void { super.renderBody(parent); - dom.addClass(parent, 'markers-panel'); + parent.classList.add('markers-panel'); const container = dom.append(parent, dom.$('.markers-panel-container')); @@ -178,7 +178,7 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { this.smallLayout = width < 600 && height > 100; if (this.smallLayout !== wasSmallLayout) { if (this.filterActionBar) { - dom.toggleClass(this.filterActionBar.getContainer(), 'hide', !this.smallLayout); + this.filterActionBar.getContainer().classList.toggle('hide', !this.smallLayout); } } const contentHeight = this.smallLayout ? height - 44 : height; @@ -395,8 +395,8 @@ export class MarkersView extends ViewPane implements IMarkerFilterController { private createFilterActionBar(parent: HTMLElement): void { this.filterActionBar = this._register(new ActionBar(parent, { actionViewItemProvider: action => this.getActionViewItem(action) })); - dom.addClass(this.filterActionBar.getContainer(), 'markers-panel-filter-container'); - dom.toggleClass(this.filterActionBar.getContainer(), 'hide', !this.smallLayout); + this.filterActionBar.getContainer().classList.add('markers-panel-filter-container'); + this.filterActionBar.getContainer().classList.toggle('hide', !this.smallLayout); } private createMessageBox(parent: HTMLElement): void { @@ -914,7 +914,7 @@ class MarkersTree extends WorkbenchObjectTree { } toggleVisibility(hide: boolean): void { - dom.toggleClass(this.container, 'hidden', hide); + this.container.classList.toggle('hidden', hide); } } diff --git a/src/vs/workbench/contrib/markers/browser/markersViewActions.ts b/src/vs/workbench/contrib/markers/browser/markersViewActions.ts index 0f85b179dc5..5732761d20a 100644 --- a/src/vs/workbench/contrib/markers/browser/markersViewActions.ts +++ b/src/vs/workbench/contrib/markers/browser/markersViewActions.ts @@ -250,7 +250,7 @@ class FiltersDropdownMenuActionViewItem extends DropdownMenuActionViewItem { } updateChecked(): void { - DOM.toggleClass(this.element!, 'checked', this._action.checked); + this.element!.classList.toggle('checked', this._action.checked); } } @@ -285,7 +285,7 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem { render(container: HTMLElement): void { this.container = container; - DOM.addClass(this.container, 'markers-panel-action-filter-container'); + this.container.classList.add('markers-panel-action-filter-container'); this.element = DOM.append(this.container, DOM.$('')); this.element.className = this.class; @@ -392,7 +392,7 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem { private updateBadge(): void { if (this.filterBadge) { const { total, filtered } = this.filterController.getFilterStats(); - DOM.toggleClass(this.filterBadge, 'hidden', total === filtered || filtered === 0); + this.filterBadge.classList.toggle('hidden', total === filtered || filtered === 0); this.filterBadge.textContent = localize('showing filtered problems', "Showing {0} of {1}", filtered, total); this.adjustInputBox(); } @@ -400,7 +400,7 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem { private adjustInputBox(): void { if (this.element && this.filterInputBox && this.filterBadge) { - this.filterInputBox.inputElement.style.paddingRight = DOM.hasClass(this.element, 'small') || DOM.hasClass(this.filterBadge, 'hidden') ? '25px' : '150px'; + this.filterInputBox.inputElement.style.paddingRight = this.element.classList.contains('small') || this.filterBadge.classList.contains('hidden') ? '25px' : '150px'; } } @@ -430,7 +430,7 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem { protected updateClass(): void { if (this.element && this.container) { this.element.className = this.class; - DOM.toggleClass(this.container, 'grow', DOM.hasClass(this.element, 'grow')); + this.container.classList.toggle('grow', this.element.classList.contains('grow')); this.adjustInputBox(); } } diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index 337746000d6..262c391623d 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -35,7 +35,6 @@ import { ISelectOptionItem } from 'vs/base/browser/ui/selectBox/selectBox'; import { groupBy } from 'vs/base/common/arrays'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { editorBackground, selectBorder } from 'vs/platform/theme/common/colorRegistry'; -import { addClass } from 'vs/base/browser/dom'; import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; export class OutputViewPane extends ViewPane { @@ -90,7 +89,7 @@ export class OutputViewPane extends ViewPane { renderBody(container: HTMLElement): void { super.renderBody(container); this.editor.create(container); - addClass(container, 'output-view'); + container.classList.add('output-view'); const codeEditor = this.editor.getControl(); codeEditor.setAriaOptions({ role: 'document', activeDescendant: undefined }); this._register(codeEditor.onDidChangeModelContent(() => { @@ -293,7 +292,7 @@ class SwitchOutputActionViewItem extends SelectActionViewItem { render(container: HTMLElement): void { super.render(container); - addClass(container, 'switch-output'); + container.classList.add('switch-output'); this._register(attachStylerCallback(this.themeService, { selectBorder }, colors => { container.style.borderColor = colors.selectBorder ? `${colors.selectBorder}` : ''; })); diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index fc27aa4c3ba..de11973bf42 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -358,7 +358,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP this._register(this.recordKeysAction.onDidChange(e => { if (e.checked !== undefined) { - DOM.toggleClass(recordingBadge, 'disabled', !e.checked); + recordingBadge.classList.toggle('disabled', !e.checked); if (e.checked) { this.searchWidget.inputBox.setPlaceHolder(keybindingsSearchPlaceholder); this.searchWidget.inputBox.setAriaLabel(keybindingsSearchPlaceholder); @@ -424,7 +424,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP private layoutSearchWidget(dimension: DOM.Dimension): void { this.searchWidget.layout(dimension); - DOM.toggleClass(this.headerContainer, 'small', dimension.width < 400); + this.headerContainer.classList.toggle('small', dimension.width < 400); this.searchWidget.inputBox.inputElement.style.paddingRight = `${DOM.getTotalWidth(this.actionsContainer) + 12}px`; } @@ -474,10 +474,10 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP this._register(this.keybindingsList.onContextMenu(e => this.onContextMenu(e))); this._register(this.keybindingsList.onDidChangeFocus(e => this.onFocusChange(e))); this._register(this.keybindingsList.onDidFocus(() => { - DOM.addClass(this.keybindingsList.getHTMLElement(), 'focused'); + this.keybindingsList.getHTMLElement().classList.add('focused'); })); this._register(this.keybindingsList.onDidBlur(() => { - DOM.removeClass(this.keybindingsList.getHTMLElement(), 'focused'); + this.keybindingsList.getHTMLElement().classList.remove('focused'); this.keybindingFocusContextKey.reset(); })); this._register(this.keybindingsList.onMouseDblClick(() => { @@ -821,7 +821,7 @@ class KeybindingItemRenderer implements IListRenderer { - DOM.toggleClass(this.settingsSwitcherBar.domNode, 'empty-workbench', this.contextService.getWorkbenchState() === WorkbenchState.EMPTY); + this.settingsSwitcherBar.domNode.classList.toggle('empty-workbench', this.contextService.getWorkbenchState() === WorkbenchState.EMPTY); this.userRemoteSettings.enabled = !!(this.options.enableRemoteSettings && this.environmentService.configuration.remoteAuthority); this.workspaceSettings.enabled = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY; this.folderSettings.getAction().enabled = this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.contextService.getWorkspace().folders.length > 0; @@ -697,13 +697,13 @@ export class SearchWidget extends Widget { layout(dimension: DOM.Dimension) { if (dimension.width < 400) { if (this.countElement) { - DOM.addClass(this.countElement, 'hide'); + this.countElement.classList.add('hide'); } this.inputBox.inputElement.style.paddingRight = '0px'; } else { if (this.countElement) { - DOM.removeClass(this.countElement, 'hide'); + this.countElement.classList.remove('hide'); } this.inputBox.inputElement.style.paddingRight = this.getControlsWidth() + 'px'; From ab566ed1feea04b3d076cb19cbd9a9a3c505a907 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 8 Sep 2020 13:48:56 +0200 Subject: [PATCH 51/98] use async await --- .../common/extensionGalleryService.ts | 360 +++++++++--------- 1 file changed, 175 insertions(+), 185 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 72975414203..e352246246d 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -381,10 +381,10 @@ export class ExtensionGalleryService implements IExtensionGalleryService { } } - private getCompatibleExtensionByEngine(arg1: IExtensionIdentifier | IGalleryExtension, version?: string): Promise { + private async getCompatibleExtensionByEngine(arg1: IExtensionIdentifier | IGalleryExtension, version?: string): Promise { const extension: IGalleryExtension | null = isIExtensionIdentifier(arg1) ? null : arg1; if (extension && extension.properties.engine && isEngineValid(extension.properties.engine, this.productService.version)) { - return Promise.resolve(extension); + return extension; } const { id, uuid } = extension ? extension.identifier : arg1; let query = new Query() @@ -398,40 +398,38 @@ export class ExtensionGalleryService implements IExtensionGalleryService { query = query.withFilter(FilterType.ExtensionName, id); } - return this.queryGallery(query, CancellationToken.None) - .then(({ galleryExtensions }) => { - const [rawExtension] = galleryExtensions; - if (!rawExtension || !rawExtension.versions.length) { - return null; + const { galleryExtensions } = await this.queryGallery(query, CancellationToken.None); + const [rawExtension] = galleryExtensions; + if (!rawExtension || !rawExtension.versions.length) { + return null; + } + + if (version) { + const versionAsset = rawExtension.versions.filter(v => v.version === version)[0]; + if (versionAsset) { + const extension = toExtension(rawExtension, versionAsset, 0, query); + if (extension.properties.engine && isEngineValid(extension.properties.engine, this.productService.version)) { + return extension; } - if (version) { - const versionAsset = rawExtension.versions.filter(v => v.version === version)[0]; - if (versionAsset) { - const extension = toExtension(rawExtension, versionAsset, 0, query); - if (extension.properties.engine && isEngineValid(extension.properties.engine, this.productService.version)) { - return extension; - } - } - return null; - } - return this.getLastValidExtensionVersion(rawExtension, rawExtension.versions) - .then(rawVersion => { - if (rawVersion) { - return toExtension(rawExtension, rawVersion, 0, query); - } - return null; - }); - }); + } + return null; + } + + const rawVersion = await this.getLastValidExtensionVersion(rawExtension, rawExtension.versions); + if (rawVersion) { + return toExtension(rawExtension, rawVersion, 0, query); + } + return null; } query(token: CancellationToken): Promise>; query(options: IQueryOptions, token: CancellationToken): Promise>; - query(arg1: any, arg2?: any): Promise> { + async query(arg1: any, arg2?: any): Promise> { const options: IQueryOptions = CancellationToken.isCancellationToken(arg1) ? {} : arg1; const token: CancellationToken = CancellationToken.isCancellationToken(arg1) ? arg1 : arg2; if (!this.isEnabled()) { - return Promise.reject(new Error('No extension gallery service configured.')); + throw new Error('No extension gallery service configured.'); } const type = options.names ? 'ids' : (options.text ? 'text' : 'all'); @@ -496,85 +494,80 @@ export class ExtensionGalleryService implements IExtensionGalleryService { query = query.withSortOrder(options.sortOrder); } - return this.queryGallery(query, token).then(({ galleryExtensions, total }) => { - const extensions = galleryExtensions.map((e, index) => toExtension(e, e.versions[0], index, query, options.source)); - const pageSize = query.pageSize; - const getPage = (pageIndex: number, ct: CancellationToken) => { - if (ct.isCancellationRequested) { - return Promise.reject(canceled()); - } + const { galleryExtensions, total } = await this.queryGallery(query, token); + const extensions = galleryExtensions.map((e, index) => toExtension(e, e.versions[0], index, query, options.source)); + const getPage = async (pageIndex: number, ct: CancellationToken) => { + if (ct.isCancellationRequested) { + throw canceled(); + } + const nextPageQuery = query.withPage(pageIndex + 1); + const { galleryExtensions } = await this.queryGallery(nextPageQuery, ct); + return galleryExtensions.map((e, index) => toExtension(e, e.versions[0], index, nextPageQuery, options.source)); + }; - const nextPageQuery = query.withPage(pageIndex + 1); - return this.queryGallery(nextPageQuery, ct) - .then(({ galleryExtensions }) => galleryExtensions.map((e, index) => toExtension(e, e.versions[0], index, nextPageQuery, options.source))); - }; - - return { firstPage: extensions, total, pageSize, getPage } as IPager; - }); + return { firstPage: extensions, total, pageSize: query.pageSize, getPage } as IPager; } - private queryGallery(query: Query, token: CancellationToken): Promise<{ galleryExtensions: IRawGalleryExtension[], total: number; }> { + private async queryGallery(query: Query, token: CancellationToken): Promise<{ galleryExtensions: IRawGalleryExtension[], total: number; }> { + if (!this.isEnabled()) { + throw new Error('No extension gallery service configured.'); + } + // 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.')); + const commonHeaders = await this.commonHeadersPromise; + const data = JSON.stringify(query.raw); + const headers = { + ...commonHeaders, + 'Content-Type': 'application/json', + 'Accept': 'application/json;api-version=3.0-preview.1', + 'Accept-Encoding': 'gzip', + 'Content-Length': String(data.length) + }; + + const context = await this.requestService.request({ + type: 'POST', + url: this.api('/extensionquery'), + data, + headers + }, token); + + if (context.res.statusCode && context.res.statusCode >= 400 && context.res.statusCode < 500) { + return { galleryExtensions: [], total: 0 }; } - return this.commonHeadersPromise.then(commonHeaders => { - const data = JSON.stringify(query.raw); - const headers = { - ...commonHeaders, - 'Content-Type': 'application/json', - 'Accept': 'application/json;api-version=3.0-preview.1', - 'Accept-Encoding': 'gzip', - 'Content-Length': String(data.length) - }; - return this.requestService.request({ - type: 'POST', - url: this.api('/extensionquery'), - data, - headers - }, token).then(context => { + const result = await asJson(context); + if (result) { + const r = result.results[0]; + const galleryExtensions = r.extensions; + const resultCount = r.resultMetadata && r.resultMetadata.filter(m => m.metadataType === 'ResultCount')[0]; + const total = resultCount && resultCount.metadataItems.filter(i => i.name === 'TotalCount')[0].count || 0; - if (context.res.statusCode && context.res.statusCode >= 400 && context.res.statusCode < 500) { - return { galleryExtensions: [], total: 0 }; - } - - return asJson(context).then(result => { - if (result) { - const r = result.results[0]; - const galleryExtensions = r.extensions; - const resultCount = r.resultMetadata && r.resultMetadata.filter(m => m.metadataType === 'ResultCount')[0]; - const total = resultCount && resultCount.metadataItems.filter(i => i.name === 'TotalCount')[0].count || 0; - - return { galleryExtensions, total }; - } - return { galleryExtensions: [], total: 0 }; - }); - }); - }); + return { galleryExtensions, total }; + } + return { galleryExtensions: [], total: 0 }; } - reportStatistic(publisher: string, name: string, version: string, type: StatisticType): Promise { + async reportStatistic(publisher: string, name: string, version: string, type: StatisticType): Promise { if (!this.isEnabled()) { - return Promise.resolve(undefined); + return undefined; } - return this.commonHeadersPromise.then(commonHeaders => { - const headers = { ...commonHeaders, Accept: '*/*;api-version=4.0-preview.1' }; - - return this.requestService.request({ + const commonHeaders = await this.commonHeadersPromise; + const headers = { ...commonHeaders, Accept: '*/*;api-version=4.0-preview.1' }; + try { + await this.requestService.request({ type: 'POST', url: this.api(`/publishers/${publisher}/extensions/${name}/${version}/stats?statType=${type}`), headers - }, CancellationToken.None).then(undefined, () => undefined); - }); + }, CancellationToken.None); + } catch (error) { /* Ignore */ } } - download(extension: IGalleryExtension, location: URI, operation: InstallOperation): Promise { + async download(extension: IGalleryExtension, location: URI, operation: InstallOperation): Promise { this.logService.trace('ExtensionGalleryService#download', extension.identifier.id); const data = getGalleryExtensionTelemetryData(extension); const startTime = new Date().getTime(); @@ -594,46 +587,46 @@ export class ExtensionGalleryService implements IExtensionGalleryService { fallbackUri: `${extension.assets.download.fallbackUri}?${operationParam}=true` } : extension.assets.download; - return this.getAsset(downloadAsset) - .then(context => this.fileService.writeFile(location, context.stream)) - .then(() => log(new Date().getTime() - startTime)); + const context = await this.getAsset(downloadAsset); + await this.fileService.writeFile(location, context.stream); + log(new Date().getTime() - startTime); } - getReadme(extension: IGalleryExtension, token: CancellationToken): Promise { + async getReadme(extension: IGalleryExtension, token: CancellationToken): Promise { if (extension.assets.readme) { - return this.getAsset(extension.assets.readme, {}, token) - .then(context => asText(context)) - .then(content => content || ''); + const context = await this.getAsset(extension.assets.readme, {}, token); + const content = await asText(context); + return content || ''; } - return Promise.resolve(''); + return ''; } - getManifest(extension: IGalleryExtension, token: CancellationToken): Promise { + async getManifest(extension: IGalleryExtension, token: CancellationToken): Promise { if (extension.assets.manifest) { - return this.getAsset(extension.assets.manifest, {}, token) - .then(asText) - .then(text => text ? JSON.parse(text) : null); + const context = await this.getAsset(extension.assets.manifest, {}, token); + const text = await asText(context); + return text ? JSON.parse(text) : null; } - return Promise.resolve(null); + return null; } - getCoreTranslation(extension: IGalleryExtension, languageId: string): Promise { + async getCoreTranslation(extension: IGalleryExtension, languageId: string): Promise { const asset = extension.assets.coreTranslations.filter(t => t[0] === languageId.toUpperCase())[0]; if (asset) { - return this.getAsset(asset[1]) - .then(asText) - .then(text => text ? JSON.parse(text) : null); + const context = await this.getAsset(asset[1]); + const text = await asText(context); + return text ? JSON.parse(text) : null; } - return Promise.resolve(null); + return null; } - getChangelog(extension: IGalleryExtension, token: CancellationToken): Promise { + async getChangelog(extension: IGalleryExtension, token: CancellationToken): Promise { if (extension.assets.changelog) { - return this.getAsset(extension.assets.changelog, {}, token) - .then(context => asText(context)) - .then(content => content || ''); + const context = await this.getAsset(extension.assets.changelog, {}, token); + const content = await asText(context); + return content || ''; } - return Promise.resolve(''); + return ''; } async getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise { @@ -668,48 +661,45 @@ export class ExtensionGalleryService implements IExtensionGalleryService { return result; } - private getAsset(asset: IGalleryExtensionAsset, options: IRequestOptions = {}, token: CancellationToken = CancellationToken.None): Promise { - return this.commonHeadersPromise.then(commonHeaders => { - const baseOptions = { type: 'GET' }; - const headers = { ...commonHeaders, ...(options.headers || {}) }; - options = { ...options, ...baseOptions, headers }; + private async getAsset(asset: IGalleryExtensionAsset, options: IRequestOptions = {}, token: CancellationToken = CancellationToken.None): Promise { + const commonHeaders = await this.commonHeadersPromise; + const baseOptions = { type: 'GET' }; + const headers = { ...commonHeaders, ...(options.headers || {}) }; + options = { ...options, ...baseOptions, headers }; - const url = asset.uri; - const fallbackUrl = asset.fallbackUri; - const firstOptions = { ...options, url }; + const url = asset.uri; + const fallbackUrl = asset.fallbackUri; + const firstOptions = { ...options, url }; - return this.requestService.request(firstOptions, token) - .then(context => { - if (context.res.statusCode === 200) { - return Promise.resolve(context); - } + try { + const context = await this.requestService.request(firstOptions, token); + if (context.res.statusCode === 200) { + return context; + } + const message = await asText(context); + throw new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`); + } catch (err) { + if (isPromiseCanceledError(err)) { + throw err; + } - return asText(context) - .then(message => Promise.reject(new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`))); - }) - .then(undefined, err => { - if (isPromiseCanceledError(err)) { - return Promise.reject(err); - } + const message = getErrorMessage(err); + type GalleryServiceCDNFallbackClassification = { + url: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + message: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + }; + type GalleryServiceCDNFallbackEvent = { + url: string; + message: string; + }; + this.telemetryService.publicLog2('galleryService:cdnFallback', { url, message }); - const message = getErrorMessage(err); - type GalleryServiceCDNFallbackClassification = { - url: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - message: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - }; - type GalleryServiceCDNFallbackEvent = { - url: string; - message: string; - }; - this.telemetryService.publicLog2('galleryService:cdnFallback', { url, message }); - - const fallbackOptions = { ...options, url: fallbackUrl }; - return this.requestService.request(fallbackOptions, token); - }); - }); + const fallbackOptions = { ...options, url: fallbackUrl }; + return this.requestService.request(fallbackOptions, token); + } } - private getLastValidExtensionVersion(extension: IRawGalleryExtension, versions: IRawGalleryExtensionVersion[]): Promise { + private async getLastValidExtensionVersion(extension: IRawGalleryExtension, versions: IRawGalleryExtensionVersion[]): Promise { const version = this.getLastValidExtensionVersionFromProperties(extension, versions); if (version) { return version; @@ -717,82 +707,82 @@ export class ExtensionGalleryService implements IExtensionGalleryService { return this.getLastValidExtensionVersionRecursively(extension, versions); } - private getLastValidExtensionVersionFromProperties(extension: IRawGalleryExtension, versions: IRawGalleryExtensionVersion[]): Promise | null { + private getLastValidExtensionVersionFromProperties(extension: IRawGalleryExtension, versions: IRawGalleryExtensionVersion[]): IRawGalleryExtensionVersion | null { for (const version of versions) { const engine = getEngine(version); if (!engine) { return null; } if (isEngineValid(engine, this.productService.version)) { - return Promise.resolve(version); + return version; } } return null; } - private getEngine(version: IRawGalleryExtensionVersion): Promise { + private async getEngine(version: IRawGalleryExtensionVersion): Promise { const engine = getEngine(version); if (engine) { - return Promise.resolve(engine); + return engine; } - const manifest = getVersionAsset(version, AssetType.Manifest); - if (!manifest) { - return Promise.reject('Manifest was not found'); + const manifestAsset = getVersionAsset(version, AssetType.Manifest); + if (!manifestAsset) { + throw new Error('Manifest was not found'); } const headers = { 'Accept-Encoding': 'gzip' }; - return this.getAsset(manifest, { headers }) - .then(context => asJson(context)) - .then(manifest => manifest ? manifest.engines.vscode : Promise.reject('Error while reading manifest')); + const context = await this.getAsset(manifestAsset, { headers }); + const manifest = await asJson(context); + if (manifest) { + return manifest.engines.vscode; + } + + throw new Error('Error while reading manifest'); } - private getLastValidExtensionVersionRecursively(extension: IRawGalleryExtension, versions: IRawGalleryExtensionVersion[]): Promise { + private async getLastValidExtensionVersionRecursively(extension: IRawGalleryExtension, versions: IRawGalleryExtensionVersion[]): Promise { if (!versions.length) { - return Promise.resolve(null); + return null; } const version = versions[0]; - return this.getEngine(version) - .then(engine => { - if (!isEngineValid(engine, this.productService.version)) { - return this.getLastValidExtensionVersionRecursively(extension, versions.slice(1)); - } + const engine = await this.getEngine(version); + if (!isEngineValid(engine, this.productService.version)) { + return this.getLastValidExtensionVersionRecursively(extension, versions.slice(1)); + } - version.properties = version.properties || []; - version.properties.push({ key: PropertyType.Engine, value: engine }); - return version; - }); + version.properties = version.properties || []; + version.properties.push({ key: PropertyType.Engine, value: engine }); + return version; } - getExtensionsReport(): Promise { + async getExtensionsReport(): Promise { if (!this.isEnabled()) { - return Promise.reject(new Error('No extension gallery service configured.')); + throw new Error('No extension gallery service configured.'); } if (!this.extensionsControlUrl) { - return Promise.resolve([]); + return []; } - return this.requestService.request({ type: 'GET', url: this.extensionsControlUrl }, CancellationToken.None).then(context => { - if (context.res.statusCode !== 200) { - return Promise.reject(new Error('Could not get extensions report.')); + const context = await this.requestService.request({ type: 'GET', url: this.extensionsControlUrl }, CancellationToken.None); + if (context.res.statusCode !== 200) { + throw new Error('Could not get extensions report.'); + } + + const result = await asJson(context); + const map = new Map(); + + if (result) { + for (const id of result.malicious) { + const ext = map.get(id) || { id: { id }, malicious: true, slow: false }; + ext.malicious = true; + map.set(id, ext); } + } - return asJson(context).then(result => { - const map = new Map(); - - if (result) { - for (const id of result.malicious) { - const ext = map.get(id) || { id: { id }, malicious: true, slow: false }; - ext.malicious = true; - map.set(id, ext); - } - } - - return [...map.values()]; - }); - }); + return [...map.values()]; } } From c255e914cd4342cba5d51ce7ab0d9aaab653cb39 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Sep 2020 14:30:55 +0200 Subject: [PATCH 52/98] [bat] change comment token to @rem. Fixes #105896 --- extensions/bat/language-configuration.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/bat/language-configuration.json b/extensions/bat/language-configuration.json index 17bc92f6a91..e205fb5f5c4 100644 --- a/extensions/bat/language-configuration.json +++ b/extensions/bat/language-configuration.json @@ -1,6 +1,6 @@ { "comments": { - "lineComment": "REM" + "lineComment": "@REM" }, "brackets": [ ["{", "}"], @@ -22,8 +22,8 @@ ], "folding": { "markers": { - "start": "^\\s*(::\\s*|REM\\s+)#region", - "end": "^\\s*(::\\s*|REM\\s+)#endregion" + "start": "^\\s*(::|REM|@REM)\\s*#region", + "end": "^\\s*(::|REM|@REM)\\s*#endregion" } } } From 849acd83eb4dbfb6d8a19f8503f667fcc0be8709 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Sep 2020 14:33:06 +0200 Subject: [PATCH 53/98] Treat SConstruct/SConscript files as python automatically. Fixes #105623 --- extensions/python/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/python/package.json b/extensions/python/package.json index e7c75aa4ea1..f39c3d62b23 100644 --- a/extensions/python/package.json +++ b/extensions/python/package.json @@ -15,7 +15,7 @@ "id": "python", "extensions": [ ".py", ".rpy", ".pyw", ".cpy", ".gyp", ".gypi", ".pyi", ".ipy"], "aliases": [ "Python", "py" ], - "filenames": [ "Snakefile" ], + "filenames": [ "Snakefile", "SConstruct", "SConscript" ], "firstLine": "^#!\\s*/?.*\\bpython[0-9.-]*\\b", "configuration": "./language-configuration.json" }], From 5cca952f16ec999956fdfe430737cd3db9f2a0a6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Sep 2020 14:47:40 +0200 Subject: [PATCH 54/98] trusted types (#106285) --- src/vs/workbench/browser/parts/statusbar/statusbarPart.ts | 2 +- .../workbench/contrib/debug/browser/statusbarColorProvider.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index e29be7ab5a0..1877d489ea3 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -672,7 +672,7 @@ export class StatusbarPart extends Part implements IStatusbarService { this.styleElement = createStyleSheet(container); } - this.styleElement.innerHTML = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`; + this.styleElement.textContent = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor}; }`; } private doCreateStatusItem(id: string, alignment: StatusbarAlignment, ...extraClasses: string[]): HTMLElement { diff --git a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts index 9316b53c8f4..51f6147c025 100644 --- a/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts +++ b/src/vs/workbench/contrib/debug/browser/statusbarColorProvider.ts @@ -84,7 +84,7 @@ export class StatusBarColorProvider extends Themable implements IWorkbenchContri this.styleElement = createStyleSheet(container); } - this.styleElement.innerHTML = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor} !important; }`; + this.styleElement.textContent = `.monaco-workbench .part.statusbar > .items-container > .statusbar-item.has-beak:before { border-bottom-color: ${backgroundColor} !important; }`; } private getColorKey(noFolderColor: string, debuggingColor: string, normalColor: string): string { From d1ab538db51af866c146268527174a2d9befaf1f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 8 Sep 2020 14:58:06 +0200 Subject: [PATCH 55/98] editor context keys - renames and deprecations --- .../browser/parts/editor/editorGroupView.ts | 12 ++++++++++-- src/vs/workbench/common/editor.ts | 6 ++++++ .../files/browser/fileActions.contribution.ts | 12 ++++++------ .../workbench/contrib/files/browser/fileCommands.ts | 4 ++-- .../contrib/files/browser/views/openEditorsView.ts | 6 +++--- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 900ee82ecc6..2f4a553bc0a 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup'; -import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, EditorStickyContext, EditorPinnedContext } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, EditorStickyContext, EditorPinnedContext, Deprecated_EditorPinnedContext, Deprecated_EditorDirtyContext } from 'vs/workbench/common/editor'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom'; @@ -218,7 +218,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView { private handleGroupContextKeys(contextKeyService: IContextKeyService): void { const groupActiveEditorDirtyContext = EditorDirtyContext.bindTo(contextKeyService); + const deprecatedGroupActiveEditorDirtyContext = Deprecated_EditorDirtyContext.bindTo(contextKeyService); const groupActiveEditorPinnedContext = EditorPinnedContext.bindTo(contextKeyService); + const deprecatedGroupActiveEditorPinnedContext = Deprecated_EditorPinnedContext.bindTo(contextKeyService); const groupActiveEditorStickyContext = EditorStickyContext.bindTo(contextKeyService); const groupEditorsCountContext = EditorGroupEditorsCountContext.bindTo(contextKeyService); @@ -230,9 +232,14 @@ export class EditorGroupView extends Themable implements IEditorGroupView { const activeEditor = this._group.activeEditor; if (activeEditor) { groupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving()); - activeEditorListener.value = activeEditor.onDidChangeDirty(() => groupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving())); + deprecatedGroupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving()); + activeEditorListener.value = activeEditor.onDidChangeDirty(() => { + groupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving()); + deprecatedGroupActiveEditorDirtyContext.set(activeEditor.isDirty() && !activeEditor.isSaving()); + }); } else { groupActiveEditorDirtyContext.set(false); + deprecatedGroupActiveEditorDirtyContext.set(false); } }; @@ -247,6 +254,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { case GroupChangeKind.EDITOR_PIN: if (e.editor && e.editor === this._group.activeEditor) { groupActiveEditorPinnedContext.set(this._group.isPinned(this._group.activeEditor)); + deprecatedGroupActiveEditorPinnedContext.set(this._group.isPinned(this._group.activeEditor)); } break; case GroupChangeKind.EDITOR_STICKY: diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 7459f051f22..8a59d65aac2 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -30,6 +30,12 @@ export const EditorPinnedContext = new RawContextKey('activeEditorIsNot export const EditorStickyContext = new RawContextKey('activeEditorIsPinned', false); export const EditorReadonlyContext = new RawContextKey('activeEditorIsReadonly', false); +/** TODO@ben remove me eventually */ +/** @deprecated */ +export const Deprecated_EditorPinnedContext = new RawContextKey('editorPinned', false); +/** @deprecated */ +export const Deprecated_EditorDirtyContext = new RawContextKey('groupActiveEditorDirty', false); + // Editor Kind Context Keys export const ActiveEditorContext = new RawContextKey('activeEditor', null); export const ActiveEditorAvailableEditorIdsContext = new RawContextKey('activeEditorAvailableEditorIds', ''); diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index d24581d9416..13402773565 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -10,7 +10,7 @@ import { revertLocalChangesCommand, acceptLocalChangesCommand, CONFLICT_RESOLUTI import { SyncActionDescriptor, MenuId, MenuRegistry, ILocalizedString } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes'; -import { openWindowCommand, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, DirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_LABEL, newWindowCommand, ReadonlyEditorContext, OPEN_WITH_EXPLORER_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL } from 'vs/workbench/contrib/files/browser/fileCommands'; +import { openWindowCommand, COPY_PATH_COMMAND_ID, REVEAL_IN_EXPLORER_COMMAND_ID, OPEN_TO_SIDE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_COMMAND_ID, SAVE_FILE_LABEL, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL, SAVE_ALL_IN_GROUP_COMMAND_ID, OpenEditorsGroupContext, COMPARE_WITH_SAVED_COMMAND_ID, COMPARE_RESOURCE_COMMAND_ID, SELECT_FOR_COMPARE_COMMAND_ID, ResourceSelectedForCompareContext, OpenEditorsDirtyEditorContext, COMPARE_SELECTED_COMMAND_ID, REMOVE_ROOT_FOLDER_COMMAND_ID, REMOVE_ROOT_FOLDER_LABEL, SAVE_FILES_COMMAND_ID, COPY_RELATIVE_PATH_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, SAVE_FILE_WITHOUT_FORMATTING_LABEL, newWindowCommand, OpenEditorsReadonlyEditorContext, OPEN_WITH_EXPLORER_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID, NEW_UNTITLED_FILE_LABEL } from 'vs/workbench/contrib/files/browser/fileCommands'; import { CommandsRegistry, ICommandHandler } from 'vs/platform/commands/common/commands'; import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -259,7 +259,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { command: { id: SAVE_FILE_COMMAND_ID, title: SAVE_FILE_LABEL, - precondition: DirtyEditorContext + precondition: OpenEditorsDirtyEditorContext }, when: ContextKeyExpr.or( // Untitled Editors @@ -269,7 +269,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { // Not: editor groups OpenEditorsGroupContext.toNegated(), // Not: readonly editors - ReadonlyEditorContext.toNegated(), + OpenEditorsReadonlyEditorContext.toNegated(), // Not: auto save after short delay AutoSaveAfterShortDelayContext.toNegated() ) @@ -282,13 +282,13 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { command: { id: REVERT_FILE_COMMAND_ID, title: nls.localize('revert', "Revert File"), - precondition: DirtyEditorContext + precondition: OpenEditorsDirtyEditorContext }, when: ContextKeyExpr.and( // Not: editor groups OpenEditorsGroupContext.toNegated(), // Not: readonly editors - ReadonlyEditorContext.toNegated(), + OpenEditorsReadonlyEditorContext.toNegated(), // Not: untitled editors (revert closes them) ResourceContextKey.Scheme.notEqualsTo(Schemas.untitled), // Not: auto save after short delay @@ -314,7 +314,7 @@ MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, { command: { id: COMPARE_WITH_SAVED_COMMAND_ID, title: nls.localize('compareWithSaved', "Compare with Saved"), - precondition: DirtyEditorContext + precondition: OpenEditorsDirtyEditorContext }, when: ContextKeyExpr.and(ResourceContextKey.IsFileSystemResource, AutoSaveAfterShortDelayContext.toNegated(), WorkbenchListDoubleSelection.toNegated()) }); diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index 6549ba4fdcc..cf8f51deedc 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -74,8 +74,8 @@ export const SAVE_ALL_IN_GROUP_COMMAND_ID = 'workbench.files.action.saveAllInGro export const SAVE_FILES_COMMAND_ID = 'workbench.action.files.saveFiles'; export const OpenEditorsGroupContext = new RawContextKey('groupFocusedInOpenEditors', false); -export const DirtyEditorContext = new RawContextKey('dirtyEditorFocusedInOpenEditors', false); -export const ReadonlyEditorContext = new RawContextKey('readonlyEditorFocusedInOpenEditors', false); +export const OpenEditorsDirtyEditorContext = new RawContextKey('dirtyEditorFocusedInOpenEditors', false); +export const OpenEditorsReadonlyEditorContext = new RawContextKey('readonlyEditorFocusedInOpenEditors', false); export const ResourceSelectedForCompareContext = new RawContextKey('resourceSelectedForCompare', false); export const REMOVE_ROOT_FOLDER_COMMAND_ID = 'removeRootFolder'; diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index e07fd997901..c7a308d3d65 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -31,7 +31,7 @@ import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions'; -import { DirtyEditorContext, OpenEditorsGroupContext, ReadonlyEditorContext } from 'vs/workbench/contrib/files/browser/fileCommands'; +import { OpenEditorsDirtyEditorContext, OpenEditorsGroupContext, OpenEditorsReadonlyEditorContext } from 'vs/workbench/contrib/files/browser/fileCommands'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { ResourcesDropHandler, fillResourceDataTransfers, CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; @@ -243,8 +243,8 @@ export class OpenEditorsView extends ViewPane { this.resourceContext = this.instantiationService.createInstance(ResourceContextKey); this._register(this.resourceContext); this.groupFocusedContext = OpenEditorsGroupContext.bindTo(this.contextKeyService); - this.dirtyEditorFocusedContext = DirtyEditorContext.bindTo(this.contextKeyService); - this.readonlyEditorFocusedContext = ReadonlyEditorContext.bindTo(this.contextKeyService); + this.dirtyEditorFocusedContext = OpenEditorsDirtyEditorContext.bindTo(this.contextKeyService); + this.readonlyEditorFocusedContext = OpenEditorsReadonlyEditorContext.bindTo(this.contextKeyService); this._register(this.list.onContextMenu(e => this.onListContextMenu(e))); this.list.onDidChangeFocus(e => { From dbc0cfe2b7e410a3cdebca762e05a7f7cf2885a9 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 8 Sep 2020 15:37:39 +0200 Subject: [PATCH 56/98] Fix TrustedTypes violation (#106285) --- src/vs/workbench/contrib/watermark/browser/watermark.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/contrib/watermark/browser/watermark.ts b/src/vs/workbench/contrib/watermark/browser/watermark.ts index a4a16842150..d8184afce2c 100644 --- a/src/vs/workbench/contrib/watermark/browser/watermark.ts +++ b/src/vs/workbench/contrib/watermark/browser/watermark.ts @@ -141,7 +141,6 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr const dd = dom.append(dl, $('dd')); const keybinding = new KeybindingLabel(dd, OS, { renderUnboundKeybindings: true }); keybinding.set(this.keybindingService.lookupKeybinding(entry.id)); - dd.innerHTML = keybinding.element.outerHTML; }); }; From ab4892d63b5949638353d1fc0b2164ea506c1cdf Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 8 Sep 2020 15:39:32 +0200 Subject: [PATCH 57/98] Remove optional from cancellation token in task api Fixes #105818 --- src/vs/vscode.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 780ddb90d21..d3835e3aabe 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -6266,7 +6266,7 @@ declare module 'vscode' { * @param token A cancellation token. * @return an array of tasks */ - provideTasks(token?: CancellationToken): ProviderResult; + provideTasks(token: CancellationToken): ProviderResult; /** * Resolves a task that has no [`execution`](#Task.execution) set. Tasks are @@ -6281,7 +6281,7 @@ declare module 'vscode' { * @param token A cancellation token. * @return The resolved task */ - resolveTask(task: T, token?: CancellationToken): ProviderResult; + resolveTask(task: T, token: CancellationToken): ProviderResult; } /** From ec870eefbbef1ee6cfcb6a89d198c8022badffde Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Sep 2020 06:42:28 -0700 Subject: [PATCH 58/98] xterm@4.9.0-beta.32, xterm-addon-webgl@0.9.0-beta.4 Fixes #106248 Fixes #105979 Part of #101467 Part of #106072 --- package.json | 4 ++-- remote/package.json | 4 ++-- remote/web/package.json | 4 ++-- remote/web/yarn.lock | 16 ++++++++-------- remote/yarn.lock | 16 ++++++++-------- yarn.lock | 16 ++++++++-------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 554b31a01e8..76216841eca 100644 --- a/package.json +++ b/package.json @@ -71,10 +71,10 @@ "vscode-ripgrep": "^1.8.0", "vscode-sqlite3": "4.0.10", "vscode-textmate": "5.2.0", - "xterm": "4.9.0-beta.25", + "xterm": "4.9.0-beta.32", "xterm-addon-search": "0.7.0", "xterm-addon-unicode11": "0.2.0", - "xterm-addon-webgl": "0.9.0-beta.1", + "xterm-addon-webgl": "0.9.0-beta.4", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/package.json b/remote/package.json index 187c951af64..e2fac3f4e1b 100644 --- a/remote/package.json +++ b/remote/package.json @@ -20,10 +20,10 @@ "vscode-proxy-agent": "^0.5.2", "vscode-ripgrep": "^1.8.0", "vscode-textmate": "5.2.0", - "xterm": "4.9.0-beta.25", + "xterm": "4.9.0-beta.32", "xterm-addon-search": "0.7.0", "xterm-addon-unicode11": "0.2.0", - "xterm-addon-webgl": "0.9.0-beta.1", + "xterm-addon-webgl": "0.9.0-beta.4", "yauzl": "^2.9.2", "yazl": "^2.4.3" }, diff --git a/remote/web/package.json b/remote/web/package.json index fc4855b4ab7..9db946c5bbb 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -7,9 +7,9 @@ "semver-umd": "^5.5.7", "vscode-oniguruma": "1.3.1", "vscode-textmate": "5.2.0", - "xterm": "4.9.0-beta.25", + "xterm": "4.9.0-beta.32", "xterm-addon-search": "0.7.0", "xterm-addon-unicode11": "0.2.0", - "xterm-addon-webgl": "0.9.0-beta.1" + "xterm-addon-webgl": "0.9.0-beta.4" } } diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index a5498289c43..400d4d629c4 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -37,12 +37,12 @@ xterm-addon-unicode11@0.2.0: resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0.tgz#9ed0c482b353908bba27778893ca80823382737c" integrity sha512-rjFDItPc/IDoSiEnoDFwKroNwLD/7t9vYKENjrcKVZg5tgJuuUj8D4rZtP6iVCjSB1LTLYmUs4L/EmCqIyLR/Q== -xterm-addon-webgl@0.9.0-beta.1: - version "0.9.0-beta.1" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0-beta.1.tgz#e0a4e9b71db7ef8182064236844caf32833214c2" - integrity sha512-yyIYfehzaqaOTOTjSapA3sEcaGDIPn0xAiWyRIWyW5zwTZIo7FA+O4IzhgAT9b7ioJWLcPoHPUA0OFNHAx20vQ== +xterm-addon-webgl@0.9.0-beta.4: + version "0.9.0-beta.4" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0-beta.4.tgz#5f5fde50db5c06b116471bcf56ad9930884b36fa" + integrity sha512-GuCvF7Eg1nKLX6zUbJLkt5cqeeccUjf/G6fugCfrkR0EWWC6Ik5mEsEOs5UWm9vvY2kX9t16BdCrgqp8KJegEg== -xterm@4.9.0-beta.25: - version "4.9.0-beta.25" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0-beta.25.tgz#c229a144184ab7b3c3afdaff76f9d81bac58933b" - integrity sha512-NJHwuS7Qsoq/Yuobl+Au4rgol/oBNj4pGoR2R6IRnXODS5RDE4spHDofWKiUkDMlNZtPPku1W7k1kFnonDIhhg== +xterm@4.9.0-beta.32: + version "4.9.0-beta.32" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0-beta.32.tgz#d1243d3be211cc06aad3418e696e4eced995c20c" + integrity sha512-jloHNBnj6XRJt+oPkapvrXJZVsYq6se/PEgzErl0iZn9qzSB3jmWE4byumoEjXJR6EgU5ZOmNljeeEDA9jO/jA== diff --git a/remote/yarn.lock b/remote/yarn.lock index 748e983bd3c..4d3f24a8d96 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -445,15 +445,15 @@ xterm-addon-unicode11@0.2.0: resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0.tgz#9ed0c482b353908bba27778893ca80823382737c" integrity sha512-rjFDItPc/IDoSiEnoDFwKroNwLD/7t9vYKENjrcKVZg5tgJuuUj8D4rZtP6iVCjSB1LTLYmUs4L/EmCqIyLR/Q== -xterm-addon-webgl@0.9.0-beta.1: - version "0.9.0-beta.1" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0-beta.1.tgz#e0a4e9b71db7ef8182064236844caf32833214c2" - integrity sha512-yyIYfehzaqaOTOTjSapA3sEcaGDIPn0xAiWyRIWyW5zwTZIo7FA+O4IzhgAT9b7ioJWLcPoHPUA0OFNHAx20vQ== +xterm-addon-webgl@0.9.0-beta.4: + version "0.9.0-beta.4" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0-beta.4.tgz#5f5fde50db5c06b116471bcf56ad9930884b36fa" + integrity sha512-GuCvF7Eg1nKLX6zUbJLkt5cqeeccUjf/G6fugCfrkR0EWWC6Ik5mEsEOs5UWm9vvY2kX9t16BdCrgqp8KJegEg== -xterm@4.9.0-beta.25: - version "4.9.0-beta.25" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0-beta.25.tgz#c229a144184ab7b3c3afdaff76f9d81bac58933b" - integrity sha512-NJHwuS7Qsoq/Yuobl+Au4rgol/oBNj4pGoR2R6IRnXODS5RDE4spHDofWKiUkDMlNZtPPku1W7k1kFnonDIhhg== +xterm@4.9.0-beta.32: + version "4.9.0-beta.32" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0-beta.32.tgz#d1243d3be211cc06aad3418e696e4eced995c20c" + integrity sha512-jloHNBnj6XRJt+oPkapvrXJZVsYq6se/PEgzErl0iZn9qzSB3jmWE4byumoEjXJR6EgU5ZOmNljeeEDA9jO/jA== yauzl@^2.9.2: version "2.10.0" diff --git a/yarn.lock b/yarn.lock index c00f67c5de6..76dfc7c47b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10060,15 +10060,15 @@ xterm-addon-unicode11@0.2.0: resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0.tgz#9ed0c482b353908bba27778893ca80823382737c" integrity sha512-rjFDItPc/IDoSiEnoDFwKroNwLD/7t9vYKENjrcKVZg5tgJuuUj8D4rZtP6iVCjSB1LTLYmUs4L/EmCqIyLR/Q== -xterm-addon-webgl@0.9.0-beta.1: - version "0.9.0-beta.1" - resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0-beta.1.tgz#e0a4e9b71db7ef8182064236844caf32833214c2" - integrity sha512-yyIYfehzaqaOTOTjSapA3sEcaGDIPn0xAiWyRIWyW5zwTZIo7FA+O4IzhgAT9b7ioJWLcPoHPUA0OFNHAx20vQ== +xterm-addon-webgl@0.9.0-beta.4: + version "0.9.0-beta.4" + resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0-beta.4.tgz#5f5fde50db5c06b116471bcf56ad9930884b36fa" + integrity sha512-GuCvF7Eg1nKLX6zUbJLkt5cqeeccUjf/G6fugCfrkR0EWWC6Ik5mEsEOs5UWm9vvY2kX9t16BdCrgqp8KJegEg== -xterm@4.9.0-beta.25: - version "4.9.0-beta.25" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0-beta.25.tgz#c229a144184ab7b3c3afdaff76f9d81bac58933b" - integrity sha512-NJHwuS7Qsoq/Yuobl+Au4rgol/oBNj4pGoR2R6IRnXODS5RDE4spHDofWKiUkDMlNZtPPku1W7k1kFnonDIhhg== +xterm@4.9.0-beta.32: + version "4.9.0-beta.32" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0-beta.32.tgz#d1243d3be211cc06aad3418e696e4eced995c20c" + integrity sha512-jloHNBnj6XRJt+oPkapvrXJZVsYq6se/PEgzErl0iZn9qzSB3jmWE4byumoEjXJR6EgU5ZOmNljeeEDA9jO/jA== y18n@^3.2.1: version "3.2.1" From 1c3d3ae3ac550338551aad950164d67ba63f160c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 15:42:09 +0200 Subject: [PATCH 59/98] notebooks - don't allow anyone to call unregisterNotebookProvider, add names to TODO-tags --- .../api/browser/mainThreadNotebook.ts | 30 ++++++++++--------- .../workbench/api/common/extHostNotebook.ts | 2 +- .../notebook/browser/contrib/coreActions.ts | 2 +- .../notebook/browser/notebookBrowser.ts | 4 +-- .../notebook/browser/notebookEditorWidget.ts | 2 +- .../notebook/browser/notebookServiceImpl.ts | 13 ++++---- .../browser/view/renderers/webviewPreloads.ts | 2 +- .../browser/viewModel/notebookViewModel.ts | 6 ++-- .../common/model/notebookCellTextModel.ts | 2 +- .../common/model/notebookTextModel.ts | 2 +- .../notebook/common/notebookService.ts | 4 +-- .../services/notebookWorkerServiceImpl.ts | 2 +- 12 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index b0c3cc0dadd..e074d504c66 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -128,7 +128,7 @@ class DocumentAndEditorState { @extHostNamedCustomer(MainContext.MainThreadNotebook) export class MainThreadNotebooks extends Disposable implements MainThreadNotebookShape { - private readonly _notebookProviders = new Map(); + private readonly _notebookProviders = new Map(); private readonly _notebookKernelProviders = new Map, provider: IDisposable }>(); private readonly _proxy: ExtHostNotebookShape; private _toDisposeOnEditorRemove = new Map(); @@ -403,12 +403,12 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo // } } - async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise { + async $registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise { const controller: IMainNotebookController = { - supportBackup: _supportBackup, - options: options, + supportBackup, + options, reloadNotebook: async (mainthreadTextModel: NotebookTextModel) => { - const data = await this._proxy.$resolveNotebookData(_viewType, mainthreadTextModel.uri); + const data = await this._proxy.$resolveNotebookData(viewType, mainthreadTextModel.uri); if (!data) { return; } @@ -460,30 +460,32 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo return this.removeNotebookTextModel(uri); }, save: async (uri: URI, token: CancellationToken) => { - return this._proxy.$saveNotebook(_viewType, uri, token); + return this._proxy.$saveNotebook(viewType, uri, token); }, saveAs: async (uri: URI, target: URI, token: CancellationToken) => { - return this._proxy.$saveNotebookAs(_viewType, uri, target, token); + return this._proxy.$saveNotebookAs(viewType, uri, target, token); }, backup: async (uri: URI, token: CancellationToken) => { - return this._proxy.$backup(_viewType, uri, token); + return this._proxy.$backup(viewType, uri, token); } }; - this._notebookProviders.set(_viewType, controller); - this._notebookService.registerNotebookController(_viewType, _extension, controller); + const disposable = this._notebookService.registerNotebookController(viewType, extension, controller); + this._notebookProviders.set(viewType, { controller, disposable }); return; } - async $onNotebookChange(viewType: string, uri: UriComponents): Promise { + async $onNotebookChange(_viewType: string, uri: UriComponents): Promise { const textModel = this._notebookService.getNotebookTextModel(URI.from(uri)); textModel?.handleUnknownChange(); } async $unregisterNotebookProvider(viewType: string): Promise { - this._notebookProviders.delete(viewType); - this._notebookService.unregisterNotebookProvider(viewType); - return; + const entry = this._notebookProviders.get(viewType); + if (entry) { + entry.disposable.dispose(); + this._notebookProviders.delete(viewType); + } } async $registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise { diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 0566d3c40b5..91b01a2da4c 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -1259,7 +1259,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN } } - // TODO: remove document - editor one on one mapping + // TODO@rebornix: remove document - editor one on one mapping private _getEditorFromURI(uriComponents: UriComponents) { const uriStr = URI.revive(uriComponents).toString(); let editor: { editor: ExtHostNotebookEditor; } | undefined; diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 0d49ef4310c..e1bff9ff928 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -482,7 +482,7 @@ registerAction2(class extends NotebookCellAction { }); export function getActiveNotebookEditor(editorService: IEditorService): INotebookEditor | undefined { - // TODO can `isNotebookEditor` be on INotebookEditor to avoid a circular dependency? + // TODO@roblourens can `isNotebookEditor` be on INotebookEditor to avoid a circular dependency? const activeEditorPane = editorService.activeEditorPane as unknown as { isNotebookEditor?: boolean } | undefined; return activeEditorPane?.isNotebookEditor ? (editorService.activeEditorPane?.getControl() as INotebookEditor) : undefined; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 5cc672c00e1..d6cfd69e03f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -507,7 +507,7 @@ export interface INotebookCellList { layout(height?: number, width?: number): void; dispose(): void; - // TODO resolve differences between List and INotebookCellList + // TODO@roblourens resolve differences between List and INotebookCellList getFocus(): number[]; setFocus(indexes: number[]): void; setSelection(indexes: number[]): void; @@ -698,7 +698,7 @@ export function getVisibleCells(cells: CellViewModel[], hiddenRanges: ICellRange } export function getActiveNotebookEditor(editorService: IEditorService): INotebookEditor | undefined { - // TODO can `isNotebookEditor` be on INotebookEditor to avoid a circular dependency? + // TODO@rebornix can `isNotebookEditor` be on INotebookEditor to avoid a circular dependency? const activeEditorPane = editorService.activeEditorPane as unknown as { isNotebookEditor?: boolean } | undefined; return activeEditorPane?.isNotebookEditor ? (editorService.activeEditorPane?.getControl() as INotebookEditor) : undefined; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 03aac260dd6..932fbeed8c8 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1778,7 +1778,7 @@ export const notebookOutputContainerColor = registerColor('notebook.outputContai hc: null }, nls.localize('notebook.outputContainerBackgroundColor', "The Color of the notebook output container background.")); -// TODO currently also used for toolbar border, if we keep all of this, pick a generic name +// TODO@rebornix currently also used for toolbar border, if we keep all of this, pick a generic name export const CELL_TOOLBAR_SEPERATOR = registerColor('notebook.cellToolbarSeparator', { dark: Color.fromHex('#808080').transparent(0.35), light: Color.fromHex('#808080').transparent(0.35), diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 3743654a065..aaae1f57737 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -542,14 +542,13 @@ export class NotebookService extends Disposable implements INotebookService, ICu return this._notebookProviders.has(viewType); } - registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController) { + registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): IDisposable { this._notebookProviders.set(viewType, { extensionData, controller }); this._onDidChangeViewTypes.fire(); - } - - unregisterNotebookProvider(viewType: string): void { - this._notebookProviders.delete(viewType); - this._onDidChangeViewTypes.fire(); + return toDisposable(() => { + this._notebookProviders.delete(viewType); + this._onDidChangeViewTypes.fire(); + }); } registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable { @@ -657,7 +656,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu cell.outputs.forEach((output) => { if (output.outputKind === CellOutputKind.Rich) { - // TODO no string[] casting + // TODO@rebornix no string[] casting const ret = this._transformMimeTypes(output, output.outputId, textModel.metadata.displayOrder as string[] || []); const orderedMimeTypes = ret.orderedMimeTypes!; const pickedMimeTypeIndex = ret.pickedMimeTypeIndex!; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 9caa12e52b7..4355e350a66 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -88,7 +88,7 @@ function webviewPreloads() { } } - // TODO: should script with src not be removed? + // TODO@connor4312: should script with src not be removed? container.appendChild(scriptTag).parentNode!.removeChild(scriptTag); } }; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index f3f812d3dda..9be338a7cec 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -312,7 +312,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD this._register(this._notebook.emitSelections(selections => { // text model emit selection change (for example, undo/redo) // we should update the selection handle wisely - // TODO, if the editor is note selected, undo/redo should not change the focused element selection + // TODO@rebornix, if the editor is note selected, undo/redo should not change the focused element selection this.updateSelectionsFromEdits(selections); })); @@ -608,13 +608,13 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, synchronous: boolean, pushUndoStop: boolean = true, previouslyFocused: ICellViewModel[] = []) { const beforeSelections = previouslyFocused.map(e => e.handle); this._notebook.createCell2(index, source, language, type, metadata, synchronous, pushUndoStop, beforeSelections, undefined); - // TODO, rely on createCell to be sync + // TODO@rebornix, rely on createCell to be sync return this.viewCells[index]; } insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean = true): CellViewModel { this._notebook.insertCell2(index, cell, synchronous, pushUndoStop); - // TODO, rely on createCell to be sync // this will trigger it to synchronous update + // TODO@rebornix, rely on createCell to be sync // this will trigger it to synchronous update return this._viewCells[index]; } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index c2b34adefcf..aa822ae32cd 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -108,7 +108,7 @@ export class NotebookCellTextModel extends Disposable implements ICell { return this._hash; } - // TODO, raw outputs + // TODO@rebornix, raw outputs this._hash = hash([hash(this.getValue()), this._getPersisentMetadata, this.transientOptions.transientOutputs ? [] : this._outputs]); return this._hash; } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index a98f8dace0b..9b1b09e1675 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -329,7 +329,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } - this._isUntitled = false; //TODO@rebornix fishy? + this._isUntitled = false; // prepare remove for (let i = index; i < index + count; i++) { diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index 40e62b67084..3ae7401fb4c 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -46,8 +46,8 @@ export interface INotebookService { onNotebookDocumentSaved: Event; onDidChangeKernels: Event; onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined }>; - registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): void; - unregisterNotebookProvider(viewType: string): void; + registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): IDisposable; + transformEditsOutputs(textModel: NotebookTextModel, edits: ICellEditOperation[]): void; transformSpliceOutputs(textModel: NotebookTextModel, splices: NotebookCellOutputsSplice[]): void; registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable; diff --git a/src/vs/workbench/contrib/notebook/common/services/notebookWorkerServiceImpl.ts b/src/vs/workbench/contrib/notebook/common/services/notebookWorkerServiceImpl.ts index b209d8c7fd4..7693c93ec69 100644 --- a/src/vs/workbench/contrib/notebook/common/services/notebookWorkerServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/common/services/notebookWorkerServiceImpl.ts @@ -113,7 +113,7 @@ export class NotebookEditorModelManager extends Disposable { const toDispose = new DisposableStore(); - // TODO, accept Model change + // TODO@rebornix, accept Model change // toDispose.add(model.onDidChangeContent((e) => { // this._proxy.acceptModelChanged(modelUrl.toString(), e); From 66ab6580ea8053cd744da49d4e4a7c522ba36f88 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 8 Sep 2020 15:48:35 +0200 Subject: [PATCH 60/98] Add back hideHover and use on tree context menu show Fixes #106268 --- src/vs/workbench/contrib/views/browser/treeView.ts | 4 +++- src/vs/workbench/services/hover/browser/hover.ts | 5 +++++ src/vs/workbench/services/hover/browser/hoverService.ts | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/views/browser/treeView.ts b/src/vs/workbench/contrib/views/browser/treeView.ts index 64a90c8d0b6..14b2776a967 100644 --- a/src/vs/workbench/contrib/views/browser/treeView.ts +++ b/src/vs/workbench/contrib/views/browser/treeView.ts @@ -113,6 +113,7 @@ export class TreeView extends Disposable implements ITreeView { @IKeybindingService private readonly keybindingService: IKeybindingService, @INotificationService private readonly notificationService: INotificationService, @IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService, + @IHoverService private readonly hoverService: IHoverService, @IContextKeyService contextKeyService: IContextKeyService ) { super(); @@ -434,6 +435,7 @@ export class TreeView extends Disposable implements ITreeView { } private onContextMenu(treeMenus: TreeMenus, treeEvent: ITreeContextMenuEvent, actionRunner: MultipleSelectionActionRunner): void { + this.hoverService.hideHover(); const node: ITreeItem | null = treeEvent.element; if (node === null) { return; @@ -1026,7 +1028,7 @@ export class CustomTreeView extends TreeView { @IHoverService hoverService: IHoverService, @IExtensionService private readonly extensionService: IExtensionService, ) { - super(id, title, themeService, instantiationService, commandService, configurationService, progressService, contextMenuService, keybindingService, notificationService, viewDescriptorService, contextKeyService); + super(id, title, themeService, instantiationService, commandService, configurationService, progressService, contextMenuService, keybindingService, notificationService, viewDescriptorService, hoverService, contextKeyService); } setVisibility(isVisible: boolean): void { diff --git a/src/vs/workbench/services/hover/browser/hover.ts b/src/vs/workbench/services/hover/browser/hover.ts index 9bf40ada030..af6473009e7 100644 --- a/src/vs/workbench/services/hover/browser/hover.ts +++ b/src/vs/workbench/services/hover/browser/hover.ts @@ -30,6 +30,11 @@ export interface IHoverService { * ``` */ showHover(options: IHoverOptions, focus?: boolean): IDisposable | undefined; + + /** + * Hides the hover if it was visible. + */ + hideHover(): void; } export interface IHoverOptions { diff --git a/src/vs/workbench/services/hover/browser/hoverService.ts b/src/vs/workbench/services/hover/browser/hoverService.ts index 30684fc337a..28809ada167 100644 --- a/src/vs/workbench/services/hover/browser/hoverService.ts +++ b/src/vs/workbench/services/hover/browser/hoverService.ts @@ -47,6 +47,14 @@ export class HoverService implements IHoverService { return hover; } + hideHover(): void { + if (!this._currentHoverOptions) { + return; + } + this._currentHoverOptions = undefined; + this._contextViewService.hideContextView(); + } + private _intersectionChange(entries: IntersectionObserverEntry[], hover: IDisposable): void { const entry = entries[entries.length - 1]; if (!entry.isIntersecting) { From 51096957730267aaae3b53e6c3e9d0e681ab082a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Sep 2020 06:52:23 -0700 Subject: [PATCH 61/98] Update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 76216841eca..ee68a7e2cf9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.50.0", - "distro": "a2863a9e80e1f2a5d4bdb01c4ac5154c9d7d133d", + "distro": "4e70546a844cc9044dab1f605033be5c745f1940", "author": { "name": "Microsoft Corporation" }, From 8abace19c146454bd4ef1083bfc28853349b5d83 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 8 Sep 2020 16:27:23 +0200 Subject: [PATCH 62/98] explorer: Fix TrustedTypes violation #106285 --- src/vs/workbench/contrib/files/browser/views/explorerView.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index c35e3fa820b..07da7f744fd 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -811,8 +811,8 @@ export class ExplorerView extends ViewPane { } const newStyles = content.join('\n'); - if (newStyles !== this.styleElement.innerHTML) { - this.styleElement.innerHTML = newStyles; + if (newStyles !== this.styleElement.textContent) { + this.styleElement.textContent = newStyles; } } From fc4163ea0102e8b566fcc47e34a9291b5c80c648 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Tue, 8 Sep 2020 16:32:04 +0200 Subject: [PATCH 63/98] Add loginShell (microsoft/vscode-remote-release#3593) --- .../configuration-editing/schemas/attachContainer.schema.json | 1 + .../configuration-editing/schemas/devContainer.schema.json | 1 + 2 files changed, 2 insertions(+) diff --git a/extensions/configuration-editing/schemas/attachContainer.schema.json b/extensions/configuration-editing/schemas/attachContainer.schema.json index fc53bb896f1..2b7952446f0 100644 --- a/extensions/configuration-editing/schemas/attachContainer.schema.json +++ b/extensions/configuration-editing/schemas/attachContainer.schema.json @@ -50,6 +50,7 @@ "type": "string", "enum": [ "none", + "loginShell", "loginInteractiveShell", "interactiveShell" ], diff --git a/extensions/configuration-editing/schemas/devContainer.schema.json b/extensions/configuration-editing/schemas/devContainer.schema.json index 999a50e7788..b37e07fa65c 100644 --- a/extensions/configuration-editing/schemas/devContainer.schema.json +++ b/extensions/configuration-editing/schemas/devContainer.schema.json @@ -96,6 +96,7 @@ "type": "string", "enum": [ "none", + "loginShell", "loginInteractiveShell", "interactiveShell" ], From ce19502cdd88ba95c493103c5c753f54ea19c879 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 16:24:58 +0200 Subject: [PATCH 64/98] chore - tweak onDidAddNotebookDocument, onDidRemoveNotebookDocument event, use ResourceMap and fix confusion between models and editors --- .../api/browser/mainThreadNotebook.ts | 57 ++++++++----------- .../notebook/browser/notebookServiceImpl.ts | 16 +++--- .../notebook/common/notebookService.ts | 4 +- 3 files changed, 36 insertions(+), 41 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index e074d504c66..fb62baa61bb 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -7,6 +7,7 @@ import * as DOM from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Emitter } from 'vs/base/common/event'; import { combinedDisposable, Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { ResourceMap } from 'vs/base/common/map'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -134,7 +135,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo private _toDisposeOnEditorRemove = new Map(); private _currentState?: DocumentAndEditorState; private _editorEventListenersMapping: Map = new Map(); - private _documentEventListenersMapping: Map = new Map(); + private _documentEventListenersMapping: ResourceMap = new ResourceMap(); private readonly _cellStatusBarEntries: Map = new Map(); constructor( @@ -162,11 +163,11 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo } async removeNotebookTextModel(uri: URI): Promise { + // TODO@rebornix remove this? obsolete? // TODO@rebornix, remove cell should use emitDelta as well to ensure document/editor events are sent together this._proxy.$acceptDocumentAndEditorsDelta({ removedDocuments: [uri] }); - let textModelDisposableStore = this._documentEventListenersMapping.get(uri.toString()); - textModelDisposableStore?.dispose(); - this._documentEventListenersMapping.delete(URI.from(uri).toString()); + this._documentEventListenersMapping.get(uri)?.dispose(); + this._documentEventListenersMapping.delete(uri); } private _isDeltaEmpty(delta: INotebookDocumentsAndEditorsDelta) { @@ -255,40 +256,32 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo notebookEditorAddedHandler(editor); }); - const notebookDocumentAddedHandler = (doc: URI) => { - if (!this._editorEventListenersMapping.has(doc.toString())) { - const disposableStore = new DisposableStore(); - const textModel = this._notebookService.getNotebookTextModel(doc); - disposableStore.add(textModel!.onDidModelChangeProxy(e => { - this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty); - this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: { selections: textModel!.selections }, metadata: null }); - })); - disposableStore.add(textModel!.onDidSelectionChange(e => { - const selectionsChange = e ? { selections: e } : null; - this._proxy.$acceptDocumentPropertiesChanged(doc, { selections: selectionsChange, metadata: null }); - })); - - this._editorEventListenersMapping.set(textModel!.uri.toString(), disposableStore); + const notebookDocumentAddedHandler = (textModel: NotebookTextModel) => { + if (this._documentEventListenersMapping.has(textModel.uri)) { + return; } + const disposableStore = new DisposableStore(); + disposableStore.add(textModel.onDidModelChangeProxy(e => { + this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty); + this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { selections: { selections: textModel!.selections }, metadata: null }); + })); + disposableStore.add(textModel.onDidSelectionChange(e => { + const selectionsChange = e ? { selections: e } : null; + this._proxy.$acceptDocumentPropertiesChanged(textModel.uri, { selections: selectionsChange, metadata: null }); + })); + + this._documentEventListenersMapping.set(textModel.uri, disposableStore); }; - this._register(this._notebookService.onNotebookDocumentAdd((documents) => { - documents.forEach(doc => { - notebookDocumentAddedHandler(doc); - }); + this._notebookService.listNotebookDocuments().forEach(notebookDocumentAddedHandler); + this._register(this._notebookService.onDidAddNotebookDocument(document => { + notebookDocumentAddedHandler(document); this._updateState(); })); - this._notebookService.listNotebookDocuments().forEach((doc) => { - notebookDocumentAddedHandler(doc.uri); - }); - - this._register(this._notebookService.onNotebookDocumentRemove((documents) => { - documents.forEach(doc => { - this._documentEventListenersMapping.get(doc.toString())?.dispose(); - this._documentEventListenersMapping.delete(doc.toString()); - }); - + this._register(this._notebookService.onDidRemoveNotebookDocument(uri => { + this._documentEventListenersMapping.get(uri)?.dispose(); + this._documentEventListenersMapping.delete(uri); this._updateState(); })); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index aaae1f57737..28b08f6d08d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -239,10 +239,12 @@ export class NotebookService extends Disposable implements INotebookService, ICu public readonly onNotebookEditorAdd: Event = this._onNotebookEditorAdd.event; private readonly _onNotebookEditorsRemove: Emitter = this._register(new Emitter()); public readonly onNotebookEditorsRemove: Event = this._onNotebookEditorsRemove.event; - private readonly _onNotebookDocumentAdd: Emitter = this._register(new Emitter()); - public readonly onNotebookDocumentAdd: Event = this._onNotebookDocumentAdd.event; - private readonly _onNotebookDocumentRemove: Emitter = this._register(new Emitter()); - public readonly onNotebookDocumentRemove: Event = this._onNotebookDocumentRemove.event; + + private readonly _onDidAddNotebookDocument = this._register(new Emitter()); + private readonly _onDidRemoveNotebookDocument = this._register(new Emitter()); + readonly onDidAddNotebookDocument = this._onDidAddNotebookDocument.event; + readonly onDidRemoveNotebookDocument = this._onDidRemoveNotebookDocument.event; + private readonly _onNotebookDocumentSaved: Emitter = this._register(new Emitter()); public readonly onNotebookDocumentSaved: Event = this._onNotebookDocumentSaved.event; private readonly _notebookEditors = new Map(); @@ -631,7 +633,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu ); this._models.set(uri, modelData); - this._onNotebookDocumentAdd.fire([notebookModel.uri]); + this._onDidAddNotebookDocument.fire(notebookModel); // after the document is added to the store and sent to ext host, we transform the ouputs await this.transformTextModelOutputs(notebookModel); @@ -928,8 +930,8 @@ export class NotebookService extends Disposable implements INotebookService, ICu this._onNotebookEditorsRemove.fire(willRemovedEditors.map(e => e)); - this._onNotebookDocumentRemove.fire([modelData.model.uri]); - modelData?.dispose(); + this._onDidRemoveNotebookDocument.fire(modelData.model.uri); + modelData.dispose(); } } } diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index 3ae7401fb4c..99a754b4e55 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -41,8 +41,8 @@ export interface INotebookService { onDidChangeVisibleEditors: Event; onNotebookEditorAdd: Event; onNotebookEditorsRemove: Event; - onNotebookDocumentRemove: Event; - onNotebookDocumentAdd: Event; + onDidRemoveNotebookDocument: Event; + onDidAddNotebookDocument: Event; onNotebookDocumentSaved: Event; onDidChangeKernels: Event; onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelId: string | undefined }>; From 7b08ea7e023a99e28f284fe5f4bd9f9fd0d3cc3e Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 16:34:41 +0200 Subject: [PATCH 65/98] notebook update --- .vscode/notebooks/verification.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues index 79f7f8a5c0e..4e65452ea56 100644 --- a/.vscode/notebooks/verification.github-issues +++ b/.vscode/notebooks/verification.github-issues @@ -14,7 +14,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks \n$milestone=milestone:\"July 2020\"", + "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks \n$milestone=milestone:\"September 2020\"", "editable": true }, { From 12fc18ba86ae8197f8ad538e2ba280512514649d Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 16:57:12 +0200 Subject: [PATCH 66/98] Use innerText over innerHTML, https://github.com/microsoft/vscode/issues/106285 --- src/vs/workbench/browser/parts/compositePart.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts index 6f13c837218..c9c0963fed8 100644 --- a/src/vs/workbench/browser/parts/compositePart.ts +++ b/src/vs/workbench/browser/parts/compositePart.ts @@ -7,7 +7,6 @@ import 'vs/css!./media/compositepart'; import * as nls from 'vs/nls'; import { defaultGenerator } from 'vs/base/common/idGenerator'; import { IDisposable, dispose, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; -import * as strings from 'vs/base/common/strings'; import { Emitter } from 'vs/base/common/event'; import * as errors from 'vs/base/common/errors'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; @@ -413,8 +412,8 @@ export abstract class CompositePart extends Part { const $this = this; return { - updateTitle: (id, title, keybinding) => { - titleLabel.innerHTML = strings.escape(title); + updateTitle: (_id, title, keybinding) => { + titleLabel.innerText = title; titleLabel.title = keybinding ? nls.localize('titleTooltip', "{0} ({1})", title, keybinding) : title; }, From 7b93ed001c18720215cf8446253ab177c8199b21 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Sep 2020 16:59:17 +0200 Subject: [PATCH 67/98] rename to IHostColorSchemeService --- ...HostColorService.ts => browserHostColorSchemeService.ts} | 6 +++--- .../services/themes/browser/workbenchThemeService.ts | 4 ++-- .../{hostColorService.ts => hostColorSchemeService.ts} | 4 ++-- ...eHostColorService.ts => nativeHostColorSchemeService.ts} | 6 +++--- src/vs/workbench/workbench.sandbox.main.ts | 2 +- src/vs/workbench/workbench.web.main.ts | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) rename src/vs/workbench/services/themes/browser/{browserHostColorService.ts => browserHostColorSchemeService.ts} (84%) rename src/vs/workbench/services/themes/common/{hostColorService.ts => hostColorSchemeService.ts} (81%) rename src/vs/workbench/services/themes/electron-sandbox/{nativeHostColorService.ts => nativeHostColorSchemeService.ts} (84%) diff --git a/src/vs/workbench/services/themes/browser/browserHostColorService.ts b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts similarity index 84% rename from src/vs/workbench/services/themes/browser/browserHostColorService.ts rename to src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts index 71ca270e6a6..2f16e857fc7 100644 --- a/src/vs/workbench/services/themes/browser/browserHostColorService.ts +++ b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts @@ -7,10 +7,10 @@ import { Emitter, Event } from 'vs/base/common/event'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Disposable } from 'vs/base/common/lifecycle'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IHostColorService } from 'vs/workbench/services/themes/common/hostColorService'; +import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -export class BrowserHostColorService extends Disposable implements IHostColorService { +export class BrowserHostColorSchemeService extends Disposable implements IHostColorSchemeService { declare readonly _serviceBrand: undefined; @@ -46,4 +46,4 @@ export class BrowserHostColorService extends Disposable implements IHostColorSer } -registerSingleton(IHostColorService, BrowserHostColorService, true); +registerSingleton(IHostColorSchemeService, BrowserHostColorSchemeService, true); diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index a8ac5971cc0..7aa072ca36e 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -35,7 +35,7 @@ import { registerProductIconThemeSchemas } from 'vs/workbench/services/themes/co import { ILogService } from 'vs/platform/log/common/log'; import { isWeb } from 'vs/base/common/platform'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -import { IHostColorService } from 'vs/workbench/services/themes/common/hostColorService'; +import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService'; // implementation @@ -106,7 +106,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { @IExtensionResourceLoaderService private readonly extensionResourceLoaderService: IExtensionResourceLoaderService, @IWorkbenchLayoutService readonly layoutService: IWorkbenchLayoutService, @ILogService private readonly logService: ILogService, - @IHostColorService private readonly hostColorService: IHostColorService, + @IHostColorSchemeService private readonly hostColorService: IHostColorSchemeService, ) { this.container = layoutService.container; this.settings = new ThemeConfiguration(configurationService); diff --git a/src/vs/workbench/services/themes/common/hostColorService.ts b/src/vs/workbench/services/themes/common/hostColorSchemeService.ts similarity index 81% rename from src/vs/workbench/services/themes/common/hostColorService.ts rename to src/vs/workbench/services/themes/common/hostColorSchemeService.ts index c10d23e2dc0..a1fac0124e7 100644 --- a/src/vs/workbench/services/themes/common/hostColorService.ts +++ b/src/vs/workbench/services/themes/common/hostColorSchemeService.ts @@ -7,9 +7,9 @@ import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -export const IHostColorService = createDecorator('hostColorService'); +export const IHostColorSchemeService = createDecorator('hostColorSchemeService'); -export interface IHostColorService { +export interface IHostColorSchemeService { readonly _serviceBrand: undefined; diff --git a/src/vs/workbench/services/themes/electron-sandbox/nativeHostColorService.ts b/src/vs/workbench/services/themes/electron-sandbox/nativeHostColorSchemeService.ts similarity index 84% rename from src/vs/workbench/services/themes/electron-sandbox/nativeHostColorService.ts rename to src/vs/workbench/services/themes/electron-sandbox/nativeHostColorSchemeService.ts index cac81330b3e..988e308f228 100644 --- a/src/vs/workbench/services/themes/electron-sandbox/nativeHostColorService.ts +++ b/src/vs/workbench/services/themes/electron-sandbox/nativeHostColorSchemeService.ts @@ -9,9 +9,9 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { Disposable } from 'vs/base/common/lifecycle'; import { ColorScheme } from 'vs/platform/theme/common/theme'; -import { IHostColorService } from 'vs/workbench/services/themes/common/hostColorService'; +import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService'; -export class NativeHostColorService extends Disposable implements IHostColorService { +export class NativeHostColorSchemeService extends Disposable implements IHostColorSchemeService { declare readonly _serviceBrand: undefined; @@ -42,4 +42,4 @@ export class NativeHostColorService extends Disposable implements IHostColorServ } -registerSingleton(IHostColorService, NativeHostColorService, true); +registerSingleton(IHostColorSchemeService, NativeHostColorSchemeService, true); diff --git a/src/vs/workbench/workbench.sandbox.main.ts b/src/vs/workbench/workbench.sandbox.main.ts index 63d0c766333..3f5a3c61f87 100644 --- a/src/vs/workbench/workbench.sandbox.main.ts +++ b/src/vs/workbench/workbench.sandbox.main.ts @@ -38,7 +38,7 @@ import 'vs/workbench/services/workspaces/electron-sandbox/workspaceEditingServic import 'vs/workbench/services/configurationResolver/electron-sandbox/configurationResolverService'; import 'vs/workbench/services/accessibility/electron-sandbox/accessibilityService'; import 'vs/workbench/services/path/electron-sandbox/pathService'; -import 'vs/workbench/services/themes/electron-sandbox/nativeHostColorService'; +import 'vs/workbench/services/themes/electron-sandbox/nativeHostColorSchemeService'; //#endregion diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 74a2a17e1a8..099c57315cc 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -50,7 +50,7 @@ import 'vs/workbench/services/lifecycle/browser/lifecycleService'; import 'vs/workbench/services/clipboard/browser/clipboardService'; import 'vs/workbench/services/extensionResourceLoader/browser/extensionResourceLoaderService'; import 'vs/workbench/services/path/browser/pathService'; -import 'vs/workbench/services/themes/browser/browserHostColorService'; +import 'vs/workbench/services/themes/browser/browserHostColorSchemeService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; From 52e557f26b6404d3f811b8dba8c72d882be8485c Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 8 Sep 2020 17:18:06 +0200 Subject: [PATCH 68/98] API proposal for tree item icon color Part of #103120 --- src/vs/vscode.proposed.d.ts | 5 +++++ src/vs/workbench/api/common/extHostTreeViews.ts | 8 +++++++- src/vs/workbench/common/views.ts | 5 ++++- src/vs/workbench/contrib/views/browser/treeView.ts | 3 +++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 4325d62d7be..676798f8e07 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -972,6 +972,11 @@ declare module 'vscode' { */ tooltip?: string | MarkdownString | /* for compilation */ any; + /** + * When `iconPath` is a [ThemeColor](#ThemeColor) `iconColor` will be used to set the color of the icon. + */ + iconColor?: ThemeColor; + /** * @param label Label describing this item * @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the tree item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None) diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index 8621743e706..02777446909 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -13,7 +13,7 @@ import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.proto import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel, IRevealOptions } from 'vs/workbench/common/views'; import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/common/extHostCommands'; import { asPromise } from 'vs/base/common/async'; -import { TreeItemCollapsibleState, ThemeIcon, MarkdownString as MarkdownStringType } from 'vs/workbench/api/common/extHostTypes'; +import { TreeItemCollapsibleState, ThemeIcon, MarkdownString as MarkdownStringType, ThemeColor } from 'vs/workbench/api/common/extHostTypes'; import { isUndefinedOrNull, isString } from 'vs/base/common/types'; import { equals, coalesce } from 'vs/base/common/arrays'; import { ILogService } from 'vs/platform/log/common/log'; @@ -550,6 +550,7 @@ class ExtHostTreeView extends Disposable { icon, iconDark: this.getDarkIconPath(extensionTreeItem) || icon, themeIcon: extensionTreeItem.iconPath instanceof ThemeIcon ? { id: extensionTreeItem.iconPath.id } : undefined, + iconColor: this.getIconColor(extensionTreeItem), collapsibleState: isUndefinedOrNull(extensionTreeItem.collapsibleState) ? TreeItemCollapsibleState.None : extensionTreeItem.collapsibleState, accessibilityInformation: extensionTreeItem.accessibilityInformation }; @@ -563,6 +564,11 @@ class ExtHostTreeView extends Disposable { }; } + private getIconColor(extensionTreeItem: vscode.TreeItem2): ThemeColor | undefined { + checkProposedApiEnabled(this.extension); + return (extensionTreeItem.iconPath instanceof ThemeIcon) ? extensionTreeItem.iconColor : undefined; + } + private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent: TreeNode | Root, returnFirst?: boolean): TreeItemHandle { if (id) { return `${ExtHostTreeView.ID_HANDLE_PREFIX}/${id}`; diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index e50bd99f313..50a97ca01ed 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -10,7 +10,7 @@ import { RawContextKey, ContextKeyExpression } from 'vs/platform/contextkey/comm import { localize } from 'vs/nls'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { ThemeColor, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { getOrSet } from 'vs/base/common/map'; import { Registry } from 'vs/platform/registry/common/platform'; import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -644,6 +644,8 @@ export interface ITreeItem { themeIcon?: ThemeIcon; + iconColor?: ThemeColor; + resourceUri?: UriComponents; tooltip?: string | IMarkdownString; @@ -666,6 +668,7 @@ export class ResolvableTreeItem implements ITreeItem { icon?: UriComponents; iconDark?: UriComponents; themeIcon?: ThemeIcon; + iconColor?: ThemeColor; resourceUri?: UriComponents; tooltip?: string | IMarkdownString; contextValue?: string; diff --git a/src/vs/workbench/contrib/views/browser/treeView.ts b/src/vs/workbench/contrib/views/browser/treeView.ts index 14b2776a967..77c0695f107 100644 --- a/src/vs/workbench/contrib/views/browser/treeView.ts +++ b/src/vs/workbench/contrib/views/browser/treeView.ts @@ -792,6 +792,9 @@ class TreeRenderer extends Disposable implements ITreeRenderer Date: Tue, 8 Sep 2020 17:28:16 +0200 Subject: [PATCH 69/98] chore - when target might be undefined use `target?.dispose()` over `dispose(target)` --- .../base/browser/ui/breadcrumbs/breadcrumbsWidget.ts | 6 ++---- .../contrib/gotoSymbol/peek/referencesController.ts | 10 +++++----- src/vs/editor/contrib/gotoSymbol/symbolNavigation.ts | 8 ++++---- src/vs/editor/contrib/smartSelect/smartSelect.ts | 8 ++++---- src/vs/editor/contrib/snippet/snippetController2.ts | 6 +++--- src/vs/editor/contrib/suggest/suggestAlternatives.ts | 4 ++-- src/vs/editor/contrib/suggest/suggestModel.ts | 2 +- src/vs/editor/contrib/suggest/wordContextKey.ts | 4 ++-- src/vs/workbench/api/browser/mainThreadFileSystem.ts | 2 +- src/vs/workbench/api/common/extHostFileSystem.ts | 4 ++-- .../workbench/api/common/extHostLanguageFeatures.ts | 8 ++++---- .../contrib/callHierarchy/common/callHierarchy.ts | 4 ++-- .../workbench/contrib/outline/browser/outlinePane.ts | 12 ++++++------ .../contrib/snippets/browser/tabCompletion.ts | 8 ++++---- 14 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts index 59225493378..fd91a3cb625 100644 --- a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts +++ b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts @@ -118,7 +118,7 @@ export class BreadcrumbsWidget { dispose(): void { this._disposables.dispose(); - dispose(this._pendingLayout); + this._pendingLayout?.dispose(); this._onDidSelectItem.dispose(); this._onDidFocusItem.dispose(); this._onDidChangeFocus.dispose(); @@ -131,9 +131,7 @@ export class BreadcrumbsWidget { if (dim && dom.Dimension.equals(dim, this._dimension)) { return; } - if (this._pendingLayout) { - this._pendingLayout.dispose(); - } + this._pendingLayout?.dispose(); if (dim) { // only measure this._pendingLayout = this._updateDimensions(dim); diff --git a/src/vs/editor/contrib/gotoSymbol/peek/referencesController.ts b/src/vs/editor/contrib/gotoSymbol/peek/referencesController.ts index f1bbff0aa81..b7942a37a72 100644 --- a/src/vs/editor/contrib/gotoSymbol/peek/referencesController.ts +++ b/src/vs/editor/contrib/gotoSymbol/peek/referencesController.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { dispose, DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IContextKey, IContextKeyService, RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; @@ -64,8 +64,8 @@ export abstract class ReferencesController implements IEditorContribution { dispose(): void { this._referenceSearchVisible.reset(); this._disposables.dispose(); - dispose(this._widget); - dispose(this._model); + this._widget?.dispose(); + this._model?.dispose(); this._widget = undefined; this._model = undefined; } @@ -226,8 +226,8 @@ export abstract class ReferencesController implements IEditorContribution { } closeWidget(focusEditor = true): void { - dispose(this._widget); - dispose(this._model); + this._widget?.dispose(); + this._model?.dispose(); this._referenceSearchVisible.reset(); this._disposables.clear(); this._widget = undefined; diff --git a/src/vs/editor/contrib/gotoSymbol/symbolNavigation.ts b/src/vs/editor/contrib/gotoSymbol/symbolNavigation.ts index 1196c0293a7..915aae90522 100644 --- a/src/vs/editor/contrib/gotoSymbol/symbolNavigation.ts +++ b/src/vs/editor/contrib/gotoSymbol/symbolNavigation.ts @@ -55,8 +55,8 @@ class SymbolNavigationService implements ISymbolNavigationService { reset(): void { this._ctxHasSymbols.reset(); - dispose(this._currentState); - dispose(this._currentMessage); + this._currentState?.dispose(); + this._currentMessage?.dispose(); this._currentModel = undefined; this._currentIdx = -1; } @@ -138,7 +138,7 @@ class SymbolNavigationService implements ISymbolNavigationService { private _showMessage(): void { - dispose(this._currentMessage); + this._currentMessage?.dispose(); const kb = this._keybindingService.lookupKeybinding('editor.gotoNextSymbolFromResult'); const message = kb @@ -209,7 +209,7 @@ class EditorState { } private _onDidRemoveEditor(editor: ICodeEditor): void { - dispose(this._listener.get(editor)); + this._listener.get(editor)?.dispose(); this._listener.delete(editor); } } diff --git a/src/vs/editor/contrib/smartSelect/smartSelect.ts b/src/vs/editor/contrib/smartSelect/smartSelect.ts index c5e66c3b2f4..b6de17c9c99 100644 --- a/src/vs/editor/contrib/smartSelect/smartSelect.ts +++ b/src/vs/editor/contrib/smartSelect/smartSelect.ts @@ -18,7 +18,7 @@ import * as modes from 'vs/editor/common/modes'; import * as nls from 'vs/nls'; import { MenuId } from 'vs/platform/actions/common/actions'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/wordSelections'; import { BracketSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/bracketSelections'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -64,7 +64,7 @@ class SmartSelectController implements IEditorContribution { } dispose(): void { - dispose(this._selectionListener); + this._selectionListener?.dispose(); } run(forward: boolean): Promise | void { @@ -106,10 +106,10 @@ class SmartSelectController implements IEditorContribution { this._state = ranges.map(ranges => new SelectionRanges(0, ranges)); // listen to caret move and forget about state - dispose(this._selectionListener); + this._selectionListener?.dispose(); this._selectionListener = this._editor.onDidChangeCursorPosition(() => { if (!this._ignoreSelection) { - dispose(this._selectionListener); + this._selectionListener?.dispose(); this._state = undefined; } }); diff --git a/src/vs/editor/contrib/snippet/snippetController2.ts b/src/vs/editor/contrib/snippet/snippetController2.ts index 7c35372a614..6459f4402f2 100644 --- a/src/vs/editor/contrib/snippet/snippetController2.ts +++ b/src/vs/editor/contrib/snippet/snippetController2.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { dispose, DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorCommand, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { Range } from 'vs/editor/common/core/range'; @@ -75,7 +75,7 @@ export class SnippetController2 implements IEditorContribution { this._inSnippet.reset(); this._hasPrevTabstop.reset(); this._hasNextTabstop.reset(); - dispose(this._session); + this._session?.dispose(); this._snippetListener.dispose(); } @@ -211,7 +211,7 @@ export class SnippetController2 implements IEditorContribution { this._hasPrevTabstop.reset(); this._hasNextTabstop.reset(); this._snippetListener.clear(); - dispose(this._session); + this._session?.dispose(); this._session = undefined; this._modelVersionId = -1; if (resetSelection) { diff --git a/src/vs/editor/contrib/suggest/suggestAlternatives.ts b/src/vs/editor/contrib/suggest/suggestAlternatives.ts index 6c9a148e618..7c72d74d4f3 100644 --- a/src/vs/editor/contrib/suggest/suggestAlternatives.ts +++ b/src/vs/editor/contrib/suggest/suggestAlternatives.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { CompletionModel } from './completionModel'; @@ -34,7 +34,7 @@ export class SuggestAlternatives { reset(): void { this._ckOtherSuggestions.reset(); - dispose(this._listener); + this._listener?.dispose(); this._model = undefined; this._acceptNext = undefined; this._ignore = false; diff --git a/src/vs/editor/contrib/suggest/suggestModel.ts b/src/vs/editor/contrib/suggest/suggestModel.ts index bb4f269ece8..718471864de 100644 --- a/src/vs/editor/contrib/suggest/suggestModel.ts +++ b/src/vs/editor/contrib/suggest/suggestModel.ts @@ -436,7 +436,7 @@ export class SuggestModel implements IDisposable { Promise.all([completions, wordDistance]).then(async ([completions, wordDistance]) => { - dispose(this._requestToken); + this._requestToken?.dispose(); if (this._state === State.Idle) { return; diff --git a/src/vs/editor/contrib/suggest/wordContextKey.ts b/src/vs/editor/contrib/suggest/wordContextKey.ts index a8f3a87cfe8..a9558304bac 100644 --- a/src/vs/editor/contrib/suggest/wordContextKey.ts +++ b/src/vs/editor/contrib/suggest/wordContextKey.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; @@ -29,7 +29,7 @@ export class WordContextKey extends Disposable { dispose(): void { super.dispose(); - dispose(this._selectionListener); + this._selectionListener?.dispose(); this._ckAtEnd.reset(); } diff --git a/src/vs/workbench/api/browser/mainThreadFileSystem.ts b/src/vs/workbench/api/browser/mainThreadFileSystem.ts index c68894ca077..9c6e733d8ff 100644 --- a/src/vs/workbench/api/browser/mainThreadFileSystem.ts +++ b/src/vs/workbench/api/browser/mainThreadFileSystem.ts @@ -34,7 +34,7 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape { } $unregisterProvider(handle: number): void { - dispose(this._fileProvider.get(handle)); + this._fileProvider.get(handle)?.dispose(); this._fileProvider.delete(handle); } diff --git a/src/vs/workbench/api/common/extHostFileSystem.ts b/src/vs/workbench/api/common/extHostFileSystem.ts index 9c0ee143a8b..34d7d3862ed 100644 --- a/src/vs/workbench/api/common/extHostFileSystem.ts +++ b/src/vs/workbench/api/common/extHostFileSystem.ts @@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystemShape, IFileChangeDto } from './extHost.protocol'; import type * as vscode from 'vscode'; import * as files from 'vs/platform/files/common/files'; -import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { FileChangeType } from 'vs/workbench/api/common/extHostTypes'; import * as typeConverter from 'vs/workbench/api/common/extHostTypeConverters'; import { ExtHostLanguageFeatures } from 'vs/workbench/api/common/extHostLanguageFeatures'; @@ -127,7 +127,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape { } dispose(): void { - dispose(this._linkProviderRegistration); + this._linkProviderRegistration?.dispose(); } private _registerLinkProviderIfNotYetRegistered(): void { diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index c912e48141d..80258e2b7d7 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -25,7 +25,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { IURITransformer } from 'vs/base/common/uriIpc'; -import { DisposableStore, dispose } from 'vs/base/common/lifecycle'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { VSBuffer } from 'vs/base/common/buffer'; import { encodeSemanticTokensDto } from 'vs/workbench/api/common/shared/semanticTokensDto'; import { IdGenerator } from 'vs/base/common/idGenerator'; @@ -177,7 +177,7 @@ class CodeLensAdapter { } releaseCodeLenses(cachedId: number): void { - dispose(this._disposables.get(cachedId)); + this._disposables.get(cachedId)?.dispose(); this._disposables.delete(cachedId); this._cache.delete(cachedId); } @@ -455,7 +455,7 @@ class CodeActionAdapter { } public releaseCodeActions(cachedId: number): void { - dispose(this._disposables.get(cachedId)); + this._disposables.get(cachedId)?.dispose(); this._disposables.delete(cachedId); this._cache.delete(cachedId); } @@ -938,7 +938,7 @@ class SuggestAdapter { } releaseCompletionItems(id: number): any { - dispose(this._disposables.get(id)); + this._disposables.get(id)?.dispose(); this._disposables.delete(id); this._cache.delete(id); } diff --git a/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts b/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts index e895bd00e60..996eddc5b18 100644 --- a/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts +++ b/src/vs/workbench/contrib/callHierarchy/common/callHierarchy.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { onUnexpectedExternalError } from 'vs/base/common/errors'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { assertType } from 'vs/base/common/types'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -180,7 +180,7 @@ CommandsRegistry.registerCommand('_executePrepareCallHierarchy', async (accessor return [model.root]; } finally { - dispose(textModelReference); + textModelReference?.dispose(); } }); diff --git a/src/vs/workbench/contrib/outline/browser/outlinePane.ts b/src/vs/workbench/contrib/outline/browser/outlinePane.ts index 26fd54407ff..ed53348c28a 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePane.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePane.ts @@ -10,7 +10,7 @@ import { createCancelablePromise, TimeoutTimer } from 'vs/base/common/async'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { defaultGenerator } from 'vs/base/common/idGenerator'; -import { dispose, IDisposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { LRUCache } from 'vs/base/common/map'; import { escape } from 'vs/base/common/strings'; import 'vs/css!./outlinePane'; @@ -280,9 +280,9 @@ export class OutlinePane extends ViewPane { } dispose(): void { - dispose(this._disposables); - dispose(this._requestOracle); - dispose(this._editorDisposables); + this._disposables.dispose(); + this._requestOracle?.dispose(); + this._editorDisposables.dispose(); super.dispose(); } @@ -395,7 +395,7 @@ export class OutlinePane extends ViewPane { if (visible && !this._requestOracle) { this._requestOracle = this._instantiationService.createInstance(RequestOracle, (editor, event) => this._doUpdate(editor, event), DocumentSymbolProviderRegistry); } else if (!visible) { - dispose(this._requestOracle); + this._requestOracle?.dispose(); this._requestOracle = undefined; this._doUpdate(undefined, undefined); } @@ -495,7 +495,7 @@ export class OutlinePane extends ViewPane { this._progressBar.infinite().show(requestDelay); const createdModel = await OutlinePane._createOutlineModel(textModel, this._editorDisposables); - dispose(loadingMessage); + loadingMessage?.dispose(); if (!createdModel) { return; } diff --git a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts index 1b21a410386..db12da69bef 100644 --- a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts +++ b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts @@ -8,7 +8,7 @@ import { RawContextKey, IContextKeyService, ContextKeyExpr, IContextKey } from ' import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ISnippetsService } from './snippets.contribution'; import { getNonWhitespacePrefix } from './snippetsService'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable } from 'vs/base/common/lifecycle'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { Range } from 'vs/editor/common/core/range'; import { registerEditorContribution, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions'; @@ -53,8 +53,8 @@ export class TabCompletionController implements IEditorContribution { } dispose(): void { - dispose(this._configListener); - dispose(this._selectionListener); + this._configListener.dispose(); + this._selectionListener?.dispose(); } private _update(): void { @@ -62,7 +62,7 @@ export class TabCompletionController implements IEditorContribution { if (this._enabled !== enabled) { this._enabled = enabled; if (!this._enabled) { - dispose(this._selectionListener); + this._selectionListener?.dispose(); } else { this._selectionListener = this._editor.onDidChangeCursorSelection(e => this._updateSnippets()); if (this._editor.getModel()) { From 8ebad589d59d61d7aa356320face354ebacf6de0 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 08:36:06 -0700 Subject: [PATCH 70/98] deprecate onDidChangeCells --- .../api/browser/mainThreadNotebook.ts | 37 ++++++++- .../workbench/api/common/extHost.protocol.ts | 4 +- .../workbench/api/common/extHostNotebook.ts | 29 +------ .../notebook/browser/contrib/scm/scm.ts | 7 +- .../browser/viewModel/notebookViewModel.ts | 23 +++++- .../common/model/notebookTextModel.ts | 80 +++++-------------- .../contrib/notebook/common/notebookCommon.ts | 31 +++---- .../notebook/test/notebookViewModel.test.ts | 10 +-- .../notebook/test/testNotebookEditor.ts | 2 +- 9 files changed, 103 insertions(+), 120 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index c5b64e0eff4..1cd0e2fc2d3 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -13,9 +13,10 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ILogService } from 'vs/platform/log/common/log'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; -import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, DisplayOrderKey, ICellEditOperation, ICellRange, IEditor, INotebookDocumentFilter, NotebookCellMetadata, NotebookCellOutputsSplice, NotebookDocumentMetadata, NOTEBOOK_DISPLAY_ORDER, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, DisplayOrderKey, ICellEditOperation, ICellRange, IEditor, IMainCellDto, INotebookDocumentFilter, NotebookCellMetadata, NotebookCellOutputsSplice, NotebookCellsChangeType, NotebookDocumentMetadata, NOTEBOOK_DISPLAY_ORDER, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, MainContext, MainThreadNotebookShape, NotebookEditorRevealType, NotebookExtensionDescription } from '../common/extHost.protocol'; @@ -261,12 +262,44 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo notebookEditorAddedHandler(editor); }); + const cellToDto = (cell: NotebookCellTextModel): IMainCellDto => { + return { + handle: cell.handle, + uri: cell.uri, + source: cell.textBuffer.getLinesContent(), + eol: cell.textBuffer.getEOL(), + language: cell.language, + cellKind: cell.cellKind, + outputs: cell.outputs, + metadata: cell.metadata + }; + }; + const notebookDocumentAddedHandler = (doc: URI) => { if (!this._editorEventListenersMapping.has(doc.toString())) { const disposableStore = new DisposableStore(); const textModel = this._notebookService.getNotebookTextModel(doc); disposableStore.add(textModel!.onDidModelChangeProxy(e => { - this._proxy.$acceptModelChanged(textModel!.uri, e, textModel!.isDirty); + const data = + e.kind === NotebookCellsChangeType.ModelChange || e.kind === NotebookCellsChangeType.Initialize + ? { + kind: e.kind, + versionId: e.versionId, + changes: e.changes.map(diff => [diff[0], diff[1], diff[2].map(cell => cellToDto(cell as NotebookCellTextModel))] as [number, number, IMainCellDto[]]) + } + : ( + e.kind === NotebookCellsChangeType.Move + ? { + kind: e.kind, + index: e.index, + length: e.length, + newIdx: e.newIdx, + versionId: e.versionId, + cells: e.cells.map(cell => cellToDto(cell as NotebookCellTextModel)) + } + : e + ); + this._proxy.$acceptModelChanged(textModel!.uri, data, textModel!.isDirty); this._proxy.$acceptDocumentPropertiesChanged(doc, { metadata: null }); })); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 1f3a03d8a5b..42253b9837b 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { TunnelOptions } from 'vs/platform/remote/common/tunnel'; import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline'; import { revive } from 'vs/base/common/marshalling'; -import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata, INotebookCellStatusBarEntry, ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'; import { Dto } from 'vs/base/common/types'; import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; @@ -1686,7 +1686,7 @@ export interface ExtHostNotebookShape { $acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void; $acceptNotebookActiveKernelChange(event: { uri: UriComponents, providerHandle: number | undefined, kernelId: string | undefined }): void; $onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void; - $acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent, isDirty: boolean): void; + $acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void; $acceptModelSaved(uriComponents: UriComponents): void; $acceptEditorPropertiesChanged(id: string, data: INotebookEditorPropertiesChangeData): void; $acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void; diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index dc1c5fa374a..60b09ee72aa 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -22,7 +22,7 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview'; -import { addIdToOutput, CellEditType, CellOutputKind, CellStatusbarAlignment, CellUri, diff, ICellEditOperation, ICellReplaceEdit, IMainCellDto, INotebookCellStatusBarEntry, INotebookDisplayOrder, INotebookEditData, INotebookKernelInfoDto2, IProcessedOutput, NotebookCellMetadata, NotebookCellsChangedEvent, NotebookCellsChangeType, NotebookCellsSplice2, NotebookDataDto, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { addIdToOutput, CellEditType, CellOutputKind, CellStatusbarAlignment, CellUri, diff, ICellEditOperation, ICellReplaceEdit, IMainCellDto, INotebookCellStatusBarEntry, INotebookDisplayOrder, INotebookEditData, INotebookKernelInfoDto2, IProcessedOutput, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookCellsSplice2, NotebookDataDto, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import * as vscode from 'vscode'; import { Cache } from './cache'; import { ResourceMap } from 'vs/base/common/map'; @@ -316,7 +316,7 @@ export class ExtHostNotebookDocument extends Disposable { this._backup = undefined; } - acceptModelChanged(event: NotebookCellsChangedEvent, isDirty: boolean): void { + acceptModelChanged(event: NotebookCellsChangedEventDto, isDirty: boolean): void { this._versionId = event.versionId; this._isDirty = isDirty; if (event.kind === NotebookCellsChangeType.Initialize) { @@ -327,10 +327,6 @@ export class ExtHostNotebookDocument extends Disposable { this._moveCell(event.index, event.newIdx); } else if (event.kind === NotebookCellsChangeType.Output) { this._setCellOutputs(event.index, event.outputs); - } else if (event.kind === NotebookCellsChangeType.CellClearOutput) { - this._clearCellOutputs(event.index); - } else if (event.kind === NotebookCellsChangeType.CellsClearOutput) { - this._clearAllCellOutputs(); } else if (event.kind === NotebookCellsChangeType.ChangeLanguage) { this._changeCellLanguage(event.index, event.language); } else if (event.kind === NotebookCellsChangeType.ChangeCellMetadata) { @@ -424,25 +420,6 @@ export class ExtHostNotebookDocument extends Disposable { this._emitter.emitCellOutputsChange({ document: this.notebookDocument, cells: [cell.cell] }); } - private _clearCellOutputs(index: number): void { - const cell = this._cells[index].cell; - cell.outputs = []; - const event: vscode.NotebookCellOutputsChangeEvent = { document: this.notebookDocument, cells: [cell] }; - this._emitter.emitCellOutputsChange(event); - } - - private _clearAllCellOutputs(): void { - const modifedCells: vscode.NotebookCell[] = []; - this._cells.forEach(({ cell }) => { - if (cell.outputs.length !== 0) { - cell.outputs = []; - modifedCells.push(cell); - } - }); - const event: vscode.NotebookCellOutputsChangeEvent = { document: this.notebookDocument, cells: modifedCells }; - this._emitter.emitCellOutputsChange(event); - } - private _changeCellLanguage(index: number, language: string): void { const cell = this._cells[index]; const event: vscode.NotebookCellLanguageChangeEvent = { document: this.notebookDocument, cell: cell.cell, language }; @@ -1279,7 +1256,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN this._webviewComm.get(editorId)?.onDidReceiveMessage(forRendererType, message); } - $acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent, isDirty: boolean): void { + $acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void { const document = this._documents.get(URI.revive(uriComponents)); if (document) { document.acceptModelChanged(event, isDirty); diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts b/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts index 3b3601c8d7f..3e23567073b 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts @@ -14,6 +14,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no import { FileService } from 'vs/platform/files/common/fileService'; import { IFileService } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; +import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class SCMController extends Disposable implements INotebookEditorContribution { static id: string = 'workbench.notebook.findController'; @@ -47,8 +48,10 @@ export class SCMController extends Disposable implements INotebookEditorContribu this.update(); })); - this._localDisposable.add(this._notebookEditor.textModel.onDidChangeCells(() => { - this.update(); + this._localDisposable.add(this._notebookEditor.textModel.onDidModelChangeProxy((e) => { + if (e.kind === NotebookCellsChangeType.ModelChange) { + this.update(); + } })); } })); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 04fcb961000..0c5a6bd3590 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -23,7 +23,7 @@ import { NotebookEventDispatcher, NotebookMetadataChangedEvent } from 'vs/workbe import { CellFoldingState, EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel'; import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; -import { CellKind, NotebookCellMetadata, INotebookSearchOptions, ICellRange, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, NotebookCellMetadata, INotebookSearchOptions, ICellRange, NotebookCellsChangeType, ICell, NotebookCellTextModelSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { FoldingRegions } from 'vs/editor/contrib/folding/foldingRanges'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer'; @@ -251,8 +251,8 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD this.id = '$notebookViewModel' + MODEL_ID; this._instanceId = strings.singleLetterHash(MODEL_ID); - this._register(this._notebook.onDidChangeCells(e => { - const diffs = e.splices.map(splice => { + const compute = (changes: NotebookCellTextModelSplice[], synchronous: boolean) => { + const diffs = changes.map(splice => { return [splice[0], splice[1], splice[2].map(cell => { return createCellViewModel(this._instantiationService, this, cell as NotebookCellTextModel); })] as [number, number, CellViewModel[]]; @@ -275,7 +275,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD }); this._onDidChangeViewCells.fire({ - synchronous: e.synchronous, + synchronous: synchronous, splices: diffs }); @@ -306,6 +306,21 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD } this.selectionHandles = endSelectionHandles; + }; + + this._register(this._notebook.onDidModelChangeProxy(e => { + let changes: NotebookCellTextModelSplice[] = []; + + if (e.kind === NotebookCellsChangeType.ModelChange || e.kind === NotebookCellsChangeType.Initialize) { + changes = e.changes; + compute(changes, e.synchronous); + return; + } else if (e.kind === NotebookCellsChangeType.Move) { + compute([[e.index, e.length, []]], e.synchronous); + compute([[e.newIdx, 0, e.cells]], e.synchronous); + } else { + return; + } })); this._register(this._notebook.onDidChangeContent(e => { diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 2f67ae1eca2..600b8a0d420 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; -import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellTextModelSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, NotebookCellsChangedEvent, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, IMainCellDto, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellTextModelSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ITextSnapshot } from 'vs/editor/common/model'; import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo'; import { InsertCellEdit, DeleteCellEdit, MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit'; @@ -109,8 +109,7 @@ export class NotebookOperationManager { class DelayedEmitter { constructor( private readonly _onDidChangeContentEmitter: Emitter, - private readonly _onDidChangeCells: Emitter<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>, - private readonly _onDidModelChangeProxy: Emitter, + private readonly _onDidModelChangeProxy: Emitter, private readonly _increaseVersion: () => void, private readonly _textModel: NotebookTextModel @@ -121,8 +120,8 @@ class DelayedEmitter { emit(data: { triggerDirty: { value: boolean } | undefined, contentChange: { value: NotebookCellsChangeType | undefined } | undefined, - cellsChange: { value: { synchronous: boolean, splices: NotebookCellTextModelSplice[] } } | undefined, - modelProxyChange: { value: NotebookCellsChangedEvent } | undefined, + cellsChange: { value: { synchronous: boolean, splices: NotebookCellTextModelSplice[] } } | undefined, + modelProxyChange: { value: NotebookTextModelChangedEvent } | undefined, }) { this._increaseVersion(); @@ -134,10 +133,6 @@ class DelayedEmitter { this._onDidChangeContentEmitter.fire(data.contentChange.value); } - if (data.cellsChange) { - this._onDidChangeCells.fire(data.cellsChange.value); - } - if (data.modelProxyChange) { this._onDidModelChangeProxy.fire( { @@ -158,13 +153,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel private _dirty = false; protected readonly _onDidChangeDirty = this._register(new Emitter()); readonly onDidChangeDirty = this._onDidChangeDirty.event; - - private readonly _onDidChangeCells = this._register(new Emitter<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>()); - get onDidChangeCells() { return this._onDidChangeCells.event; } private readonly _emitSelections = this._register(new Emitter()); get emitSelections() { return this._emitSelections.event; } - private _onDidModelChangeProxy = this._register(new Emitter()); - get onDidModelChangeProxy(): Event { return this._onDidModelChangeProxy.event; } + private _onDidModelChangeProxy = this._register(new Emitter()); + get onDidModelChangeProxy(): Event { return this._onDidModelChangeProxy.event; } private _onDidChangeContent = this._register(new Emitter()); onDidChangeContent: Event = this._onDidChangeContent.event; private _mapping: Map = new Map(); @@ -212,7 +204,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._operationManager = new NotebookOperationManager(this._undoService, uri); this._eventEmitter = new DelayedEmitter( this._onDidChangeContent, - this._onDidChangeCells, this._onDidModelChangeProxy, () => { this._increaseVersionId(); }, this @@ -385,16 +376,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel value: { kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, - changes: diffs.map(diff => [diff[0], diff[1], diff[2].map(cell => ({ - handle: cell.handle, - uri: cell.uri, - source: cell.textBuffer.getLinesContent(), - eol: cell.textBuffer.getEOL(), - language: cell.language, - cellKind: cell.cellKind, - outputs: cell.outputs, - metadata: cell.metadata - }))] as [number, number, IMainCellDto[]]) + changes: diffs, + synchronous } } }); @@ -469,17 +452,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel [[ 0, 0, - [{ - handle: cell.handle, - uri: cell.uri, - source: cell.textBuffer.getLinesContent(), - eol: cell.textBuffer.getEOL(), - language: cell.language, - cellKind: cell.cellKind, - outputs: cell.outputs, - metadata: cell.metadata - }] - ]] + [cell] + ]], + synchronous: true }); return; @@ -511,21 +486,11 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel [[ index, 0, - cells.map(cell => ({ - handle: cell.handle, - uri: cell.uri, - source: cell.textBuffer.getLinesContent(), - eol: cell.textBuffer.getEOL(), - language: cell.language, - cellKind: cell.cellKind, - outputs: cell.outputs, - metadata: cell.metadata - })) - ]] + cells + ]], + synchronous }); - this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 0, cells]] }); - return; } @@ -542,8 +507,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]] }); - this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous }); } private _isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata) { @@ -595,7 +559,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel contentChange: { value: NotebookCellsChangeType.ChangeCellMetadata }, cellsChange: undefined, modelProxyChange: { - value: { kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata } + value: { kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata, synchronous: true } } }); } @@ -615,7 +579,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel kind: NotebookCellsChangeType.Output, versionId: this.versionId, index: this.cells.indexOf(cell), - outputs: cell.outputs ?? [] + outputs: cell.outputs ?? [], + synchronous: true } } }); @@ -637,7 +602,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel cell.language = languageId; this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this.cells.indexOf(cell), language: languageId }); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this.cells.indexOf(cell), language: languageId, synchronous: true }); } } @@ -674,7 +639,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } moveCellToIdx(index: number, length: number, newIdx: number, synchronous: boolean, pushedToUndoStack: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): boolean { - const cells = this.cells.slice(index, index + length); if (pushedToUndoStack) { this._operationManager.pushEditOperation(new MoveCellEdit(this.uri, index, length, newIdx, { moveCell: (fromIndex: number, length: number, toIndex: number, beforeSelections: number[] | undefined, endSelections: number[] | undefined) => { @@ -694,13 +658,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._onDidChangeContent.fire(NotebookCellsChangeType.Move); this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, newIdx }); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous }); } // todo, we can't emit this change as it will create a new view model and that will hold // a new reference to the document, thus - this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, length, []]] }); - this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[newIdx, 0, cells]] }); + // this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, length, []]] }); + // this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[newIdx, 0, cells]] }); if (endSelections) { this._emitSelections.fire(endSelections); } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index b598294f6c9..1634766955c 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -277,7 +277,6 @@ export interface INotebookTextModel { readonly versionId: number; languages: string[]; cells: ICell[]; - onDidChangeCells?: Event<{ synchronous: boolean, splices: NotebookCellTextModelSplice[] }>; onDidChangeContent: Event; onWillDispose(listener: () => void): IDisposable; } @@ -312,10 +311,10 @@ export type IRenderOutput = IRenderNoOutput | IInsetRenderOutput; export const outputHasDynamicHeight = (o: IRenderOutput) => o.type !== RenderOutputType.Extension && o.hasDynamicHeight; -export type NotebookCellTextModelSplice = [ +export type NotebookCellTextModelSplice = [ number /* start */, number, - ICell[] + T[] ]; export type NotebookCellOutputsSplice = [ @@ -354,9 +353,9 @@ export enum NotebookCellsChangeType { ChangeDocumentMetadata = 10 } -export interface NotebookCellsInitializeEvent { +export interface NotebookCellsInitializeEvent { readonly kind: NotebookCellsChangeType.Initialize; - readonly changes: NotebookCellsSplice2[]; + readonly changes: NotebookCellTextModelSplice[]; readonly versionId: number; } @@ -365,16 +364,18 @@ export interface NotebookCellContentChangeEvent { readonly versionId: number; } -export interface NotebookCellsModelChangedEvent { +export interface NotebookCellsModelChangedEvent { readonly kind: NotebookCellsChangeType.ModelChange; - readonly changes: NotebookCellsSplice2[]; + readonly changes: NotebookCellTextModelSplice[]; readonly versionId: number; } -export interface NotebookCellsModelMoveEvent { +export interface NotebookCellsModelMoveEvent { readonly kind: NotebookCellsChangeType.Move; readonly index: number; + readonly length: number; readonly newIdx: number; + readonly cells: T[]; readonly versionId: number; } @@ -385,17 +386,6 @@ export interface NotebookOutputChangedEvent { readonly outputs: IProcessedOutput[]; } -export interface NotebookCellClearOutputEvent { - readonly kind: NotebookCellsChangeType.CellClearOutput; - readonly index: number; - readonly versionId: number; -} - -export interface NotebookCellsClearOutputEvent { - readonly kind: NotebookCellsChangeType.CellsClearOutput; - readonly versionId: number; -} - export interface NotebookCellsChangeLanguageEvent { readonly kind: NotebookCellsChangeType.ChangeLanguage; readonly versionId: number; @@ -416,7 +406,8 @@ export interface NotebookDocumentChangeMetadataEvent { readonly metadata: NotebookDocumentMetadata | undefined; } -export type NotebookCellsChangedEvent = NotebookCellsInitializeEvent | NotebookDocumentChangeMetadataEvent | NotebookCellContentChangeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellClearOutputEvent | NotebookCellsClearOutputEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent; +export type NotebookCellsChangedEventDto = NotebookCellsInitializeEvent | NotebookDocumentChangeMetadataEvent | NotebookCellContentChangeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent; +export type NotebookTextModelChangedEvent = (NotebookCellsInitializeEvent | NotebookDocumentChangeMetadataEvent | NotebookCellContentChangeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent) & { synchronous: boolean; }; export const enum CellEditType { Replace = 1, diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index 437aecd46ac..f55d96cebfb 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -69,18 +69,18 @@ suite('NotebookViewModel', () => { ['//c', 'javascript', CellKind.Code, [], { editable: true }], ], (editor, viewModel) => { - viewModel.moveCellToIdx(0, 1, 0, false); + viewModel.moveCellToIdx(0, 1, 0, true); // no-op assert.equal(viewModel.viewCells[0].getText(), '//a'); assert.equal(viewModel.viewCells[1].getText(), '//b'); - viewModel.moveCellToIdx(0, 1, 1, false); + viewModel.moveCellToIdx(0, 1, 1, true); // b, a, c assert.equal(viewModel.viewCells[0].getText(), '//b'); assert.equal(viewModel.viewCells[1].getText(), '//a'); assert.equal(viewModel.viewCells[2].getText(), '//c'); - viewModel.moveCellToIdx(0, 1, 2, false); + viewModel.moveCellToIdx(0, 1, 2, true); // a, c, b assert.equal(viewModel.viewCells[0].getText(), '//a'); assert.equal(viewModel.viewCells[1].getText(), '//c'); @@ -100,12 +100,12 @@ suite('NotebookViewModel', () => { ['//c', 'javascript', CellKind.Code, [], { editable: true }], ], (editor, viewModel) => { - viewModel.moveCellToIdx(1, 1, 0, false); + viewModel.moveCellToIdx(1, 1, 0, true); // b, a, c assert.equal(viewModel.viewCells[0].getText(), '//b'); assert.equal(viewModel.viewCells[1].getText(), '//a'); - viewModel.moveCellToIdx(2, 1, 0, false); + viewModel.moveCellToIdx(2, 1, 0, true); // c, b, a assert.equal(viewModel.viewCells[0].getText(), '//c'); assert.equal(viewModel.viewCells[1].getText(), '//b'); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 6872b80d42b..ba46779e926 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -337,7 +337,7 @@ export class NotebookEditorTestModel extends EditorModel implements INotebookEdi ) { super(); - if (_notebook && _notebook.onDidChangeCells) { + if (_notebook && _notebook.onDidChangeContent) { this._register(_notebook.onDidChangeContent(() => { this._dirty = true; this._onDidChangeDirty.fire(); From 7a92c462c8c25fbebf984d3eb52ae20a7463606e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 8 Sep 2020 10:45:57 -0500 Subject: [PATCH 71/98] Reenable notebook smoke test #105330 --- test/smoke/src/areas/notebook/notebook.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smoke/src/areas/notebook/notebook.test.ts b/test/smoke/src/areas/notebook/notebook.test.ts index 4e946ffcbe1..4ceb37250f3 100644 --- a/test/smoke/src/areas/notebook/notebook.test.ts +++ b/test/smoke/src/areas/notebook/notebook.test.ts @@ -63,7 +63,7 @@ export function setup() { await app.workbench.notebook.waitForActiveCellEditorContents('code()'); }); - it.skip('cell action execution', async function () { + it('cell action execution', async function () { const app = this.app as Application; await app.workbench.notebook.openNotebook(); await app.workbench.notebook.insertNotebookCell('code'); From a98552c935959ac9f6bb0864c424b4c294ef5500 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 08:50:03 -0700 Subject: [PATCH 72/98] deprecate onDidChangeContent --- .../notebook/browser/contrib/scm/scm.ts | 9 +---- .../browser/viewModel/notebookViewModel.ts | 4 +- .../common/model/notebookTextModel.ts | 39 +++++++++---------- .../contrib/notebook/common/notebookCommon.ts | 2 +- .../notebook/common/notebookEditorModel.ts | 9 +++-- .../notebook/test/testNotebookEditor.ts | 4 +- 6 files changed, 30 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts b/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts index 3e23567073b..ad1885bbfb3 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts @@ -14,7 +14,6 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no import { FileService } from 'vs/platform/files/common/fileService'; import { IFileService } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; -import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; export class SCMController extends Disposable implements INotebookEditorContribution { static id: string = 'workbench.notebook.findController'; @@ -44,14 +43,8 @@ export class SCMController extends Disposable implements INotebookEditorContribu this.update(); if (this._notebookEditor.textModel) { - this._localDisposable.add(this._notebookEditor.textModel.onDidChangeContent(() => { - this.update(); - })); - this._localDisposable.add(this._notebookEditor.textModel.onDidModelChangeProxy((e) => { - if (e.kind === NotebookCellsChangeType.ModelChange) { - this.update(); - } + this.update(); })); } })); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 0c5a6bd3590..c13e2aa0c7b 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -323,8 +323,8 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD } })); - this._register(this._notebook.onDidChangeContent(e => { - if (e === NotebookCellsChangeType.ChangeDocumentMetadata) { + this._register(this._notebook.onDidModelChangeProxy(e => { + if (e.kind === NotebookCellsChangeType.ChangeDocumentMetadata) { this.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]); } })); diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 600b8a0d420..96f6c84309f 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -108,7 +108,6 @@ export class NotebookOperationManager { class DelayedEmitter { constructor( - private readonly _onDidChangeContentEmitter: Emitter, private readonly _onDidModelChangeProxy: Emitter, private readonly _increaseVersion: () => void, private readonly _textModel: NotebookTextModel @@ -119,7 +118,6 @@ class DelayedEmitter { emit(data: { triggerDirty: { value: boolean } | undefined, - contentChange: { value: NotebookCellsChangeType | undefined } | undefined, cellsChange: { value: { synchronous: boolean, splices: NotebookCellTextModelSplice[] } } | undefined, modelProxyChange: { value: NotebookTextModelChangedEvent } | undefined, }) { @@ -129,10 +127,6 @@ class DelayedEmitter { this._textModel.setDirty(true); } - if (data.contentChange) { - this._onDidChangeContentEmitter.fire(data.contentChange.value); - } - if (data.modelProxyChange) { this._onDidModelChangeProxy.fire( { @@ -157,8 +151,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel get emitSelections() { return this._emitSelections.event; } private _onDidModelChangeProxy = this._register(new Emitter()); get onDidModelChangeProxy(): Event { return this._onDidModelChangeProxy.event; } - private _onDidChangeContent = this._register(new Emitter()); - onDidChangeContent: Event = this._onDidChangeContent.event; private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); cells: NotebookCellTextModel[]; @@ -203,7 +195,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._operationManager = new NotebookOperationManager(this._undoService, uri); this._eventEmitter = new DelayedEmitter( - this._onDidChangeContent, this._onDidModelChangeProxy, () => { this._increaseVersionId(); }, this @@ -250,7 +241,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = mainCells[i].onDidChangeContent(() => { this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); }); this._cellListeners.set(mainCells[i].handle, dirtyStateListener); @@ -340,7 +332,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = cell.onDidChangeContent(() => { this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); + }); this._cellListeners.set(cell.handle, dirtyStateListener); this._mapping.set(cell.handle, cell); @@ -370,7 +364,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel // should be deferred this._eventEmitter.emit({ triggerDirty: { value: true }, - contentChange: { value: NotebookCellsChangeType.ModelChange }, cellsChange: { value: { synchronous: synchronous, splices: diffs } }, modelProxyChange: { value: { @@ -423,7 +416,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel updateNotebookMetadata(metadata: NotebookDocumentMetadata) { this.metadata = metadata; - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeDocumentMetadata); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeDocumentMetadata); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, versionId: this.versionId, metadata: this.metadata, synchronous: true }); + } insertTemplateCell(cell: NotebookCellTextModel) { @@ -439,12 +434,14 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._isUntitled = false; this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); + }); this._cellListeners.set(cell.handle, dirtyStateListener); this.setDirty(false); - this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, @@ -468,7 +465,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = cells[i].onDidChangeContent(() => { this.setDirty(true); this._increaseVersionId(); - this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); + this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); }); this._cellListeners.set(cells[i].handle, dirtyStateListener); @@ -476,7 +474,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.cells.splice(index, 0, ...cells); this.setDirty(true); - this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._increaseVersionId(); @@ -504,7 +502,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel } this.cells.splice(index, count); this.setDirty(true); - this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); + // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._increaseVersionId(); this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous }); @@ -556,7 +554,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._eventEmitter.emit({ triggerDirty: { value: triggerDirtyChange }, - contentChange: { value: NotebookCellsChangeType.ChangeCellMetadata }, cellsChange: undefined, modelProxyChange: { value: { kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata, synchronous: true } @@ -572,7 +569,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._eventEmitter.emit({ triggerDirty: { value: !this.transientOptions.transientOutputs }, - contentChange: !this.transientOptions.transientOutputs ? { value: NotebookCellsChangeType.Output } : undefined, cellsChange: undefined, modelProxyChange: { value: { @@ -580,6 +576,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel versionId: this.versionId, index: this.cells.indexOf(cell), outputs: cell.outputs ?? [], + transient: this.transientOptions.transientOutputs, synchronous: true } } @@ -655,7 +652,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const cells = this.cells.splice(index, length); this.cells.splice(newIdx, 0, ...cells); this.setDirty(true); - this._onDidChangeContent.fire(NotebookCellsChangeType.Move); + // this._onDidChangeContent.fire(NotebookCellsChangeType.Move); this._increaseVersionId(); this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous }); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 1634766955c..38f03cb2b81 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -277,7 +277,6 @@ export interface INotebookTextModel { readonly versionId: number; languages: string[]; cells: ICell[]; - onDidChangeContent: Event; onWillDispose(listener: () => void): IDisposable; } @@ -384,6 +383,7 @@ export interface NotebookOutputChangedEvent { readonly index: number; readonly versionId: number; readonly outputs: IProcessedOutput[]; + readonly transient: boolean; } export interface NotebookCellsChangeLanguageEvent { diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index 9e3a0c944a4..ec51f4838fa 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { EditorModel, IRevertOptions } from 'vs/workbench/common/editor'; import { Emitter, Event } from 'vs/base/common/event'; -import { INotebookEditorModel, NotebookDocumentBackupData } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookEditorModel, NotebookCellsChangeType, NotebookDocumentBackupData } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { URI } from 'vs/base/common/uri'; @@ -145,9 +145,12 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM this._register(this._notebook); - this._register(this._notebook.onDidChangeContent(() => { - this._onDidChangeContent.fire(); + this._register(this._notebook.onDidModelChangeProxy(e => { + if (e.kind !== NotebookCellsChangeType.Initialize) { + this._onDidChangeContent.fire(); + } })); + this._register(this._notebook.onDidChangeDirty(() => { this._onDidChangeDirty.fire(); })); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index ba46779e926..75c32be59fe 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -337,8 +337,8 @@ export class NotebookEditorTestModel extends EditorModel implements INotebookEdi ) { super(); - if (_notebook && _notebook.onDidChangeContent) { - this._register(_notebook.onDidChangeContent(() => { + if (_notebook && _notebook.onDidModelChangeProxy) { + this._register(_notebook.onDidModelChangeProxy(() => { this._dirty = true; this._onDidChangeDirty.fire(); this._onDidChangeContent.fire(); From 17d779cfd2ff2c76c79e9b050d77526255fdfe83 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 08:57:16 -0700 Subject: [PATCH 73/98] unified onDidChangeContent --- .../api/browser/mainThreadNotebook.ts | 2 +- .../notebook/browser/contrib/scm/scm.ts | 2 +- .../browser/viewModel/notebookViewModel.ts | 4 +-- .../common/model/notebookTextModel.ts | 26 +++++++++---------- .../notebook/common/notebookEditorModel.ts | 2 +- .../notebook/test/testNotebookEditor.ts | 4 +-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 1cd0e2fc2d3..a74dce50ca8 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -279,7 +279,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo if (!this._editorEventListenersMapping.has(doc.toString())) { const disposableStore = new DisposableStore(); const textModel = this._notebookService.getNotebookTextModel(doc); - disposableStore.add(textModel!.onDidModelChangeProxy(e => { + disposableStore.add(textModel!.onDidChangeContent(e => { const data = e.kind === NotebookCellsChangeType.ModelChange || e.kind === NotebookCellsChangeType.Initialize ? { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts b/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts index ad1885bbfb3..4c431ef0a48 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/scm/scm.ts @@ -43,7 +43,7 @@ export class SCMController extends Disposable implements INotebookEditorContribu this.update(); if (this._notebookEditor.textModel) { - this._localDisposable.add(this._notebookEditor.textModel.onDidModelChangeProxy((e) => { + this._localDisposable.add(this._notebookEditor.textModel.onDidChangeContent((e) => { this.update(); })); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index c13e2aa0c7b..77739cea9ed 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -308,7 +308,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD this.selectionHandles = endSelectionHandles; }; - this._register(this._notebook.onDidModelChangeProxy(e => { + this._register(this._notebook.onDidChangeContent(e => { let changes: NotebookCellTextModelSplice[] = []; if (e.kind === NotebookCellsChangeType.ModelChange || e.kind === NotebookCellsChangeType.Initialize) { @@ -323,7 +323,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD } })); - this._register(this._notebook.onDidModelChangeProxy(e => { + this._register(this._notebook.onDidChangeContent(e => { if (e.kind === NotebookCellsChangeType.ChangeDocumentMetadata) { this.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]); } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 96f6c84309f..5039c4b4b59 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -149,8 +149,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel readonly onDidChangeDirty = this._onDidChangeDirty.event; private readonly _emitSelections = this._register(new Emitter()); get emitSelections() { return this._emitSelections.event; } - private _onDidModelChangeProxy = this._register(new Emitter()); - get onDidModelChangeProxy(): Event { return this._onDidModelChangeProxy.event; } + private _onDidChangeContent = this._register(new Emitter()); + get onDidChangeContent(): Event { return this._onDidChangeContent.event; } private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); cells: NotebookCellTextModel[]; @@ -195,7 +195,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._operationManager = new NotebookOperationManager(this._undoService, uri); this._eventEmitter = new DelayedEmitter( - this._onDidModelChangeProxy, + this._onDidChangeContent, () => { this._increaseVersionId(); }, this ); @@ -242,7 +242,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.setDirty(true); this._increaseVersionId(); // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); }); this._cellListeners.set(mainCells[i].handle, dirtyStateListener); @@ -333,7 +333,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.setDirty(true); this._increaseVersionId(); // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); }); this._cellListeners.set(cell.handle, dirtyStateListener); @@ -417,7 +417,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel updateNotebookMetadata(metadata: NotebookDocumentMetadata) { this.metadata = metadata; // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeDocumentMetadata); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, versionId: this.versionId, metadata: this.metadata, synchronous: true }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, versionId: this.versionId, metadata: this.metadata, synchronous: true }); } @@ -435,7 +435,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.setDirty(true); this._increaseVersionId(); // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); }); @@ -443,7 +443,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.setDirty(false); // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); - this._onDidModelChangeProxy.fire({ + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[ @@ -466,7 +466,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.setDirty(true); this._increaseVersionId(); // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); }); this._cellListeners.set(cells[i].handle, dirtyStateListener); @@ -478,7 +478,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[ @@ -505,7 +505,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous }); } private _isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata) { @@ -599,7 +599,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel cell.language = languageId; this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this.cells.indexOf(cell), language: languageId, synchronous: true }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this.cells.indexOf(cell), language: languageId, synchronous: true }); } } @@ -655,7 +655,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel // this._onDidChangeContent.fire(NotebookCellsChangeType.Move); this._increaseVersionId(); - this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous }); + this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous }); } // todo, we can't emit this change as it will create a new view model and that will hold diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index ec51f4838fa..bc6ee9afeb8 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -145,7 +145,7 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM this._register(this._notebook); - this._register(this._notebook.onDidModelChangeProxy(e => { + this._register(this._notebook.onDidChangeContent(e => { if (e.kind !== NotebookCellsChangeType.Initialize) { this._onDidChangeContent.fire(); } diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 75c32be59fe..ba46779e926 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -337,8 +337,8 @@ export class NotebookEditorTestModel extends EditorModel implements INotebookEdi ) { super(); - if (_notebook && _notebook.onDidModelChangeProxy) { - this._register(_notebook.onDidModelChangeProxy(() => { + if (_notebook && _notebook.onDidChangeContent) { + this._register(_notebook.onDidChangeContent(() => { this._dirty = true; this._onDidChangeDirty.fire(); this._onDidChangeContent.fire(); From a7a501f07a367f7de74e876a0b827deff9721949 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 8 Sep 2020 09:05:17 -0700 Subject: [PATCH 74/98] node-pty@0.10.0-beta17 Fixes #105957 --- package.json | 2 +- remote/package.json | 2 +- remote/yarn.lock | 8 ++++---- yarn.lock | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index ee68a7e2cf9..92cfce98287 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "native-is-elevated": "0.4.1", "native-keymap": "2.2.0", "native-watchdog": "1.3.0", - "node-pty": "0.10.0-beta8", + "node-pty": "0.10.0-beta17", "semver-umd": "^5.5.7", "spdlog": "^0.11.1", "sudo-prompt": "9.1.1", diff --git a/remote/package.json b/remote/package.json index e2fac3f4e1b..3b733672a3e 100644 --- a/remote/package.json +++ b/remote/package.json @@ -12,7 +12,7 @@ "jschardet": "2.2.1", "minimist": "^1.2.5", "native-watchdog": "1.3.0", - "node-pty": "0.10.0-beta8", + "node-pty": "0.10.0-beta17", "semver-umd": "^5.5.7", "spdlog": "^0.11.1", "vscode-nsfw": "1.2.8", diff --git a/remote/yarn.lock b/remote/yarn.lock index 4d3f24a8d96..2dfcb19abc6 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -294,10 +294,10 @@ node-addon-api@1.6.2: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== -node-pty@0.10.0-beta8: - version "0.10.0-beta8" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta8.tgz#f4aa56c71a794f4580373a3030dfebd25240c6db" - integrity sha512-Ul/hLsadC0SvvShxpne+kq2ebSMcitewlNhrwoXXBvFdCqxJt7Ai1AgMhH7AKBUp06uBeYXThJ2ihTszrkdnYw== +node-pty@0.10.0-beta17: + version "0.10.0-beta17" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta17.tgz#962d4a3f4dc6772385e0cad529c209cef3bc79e6" + integrity sha512-tn7EANQacnAvnOQCImvgag1DL0tVmUoY/1yIZbh3u/BBpvCcGHLZJNn7TXheodRLr6hmGSUS2VbfcUr9p0gOug== dependencies: nan "^2.14.0" diff --git a/yarn.lock b/yarn.lock index 76dfc7c47b9..7712ff05454 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6288,10 +6288,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-pty@0.10.0-beta8: - version "0.10.0-beta8" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta8.tgz#f4aa56c71a794f4580373a3030dfebd25240c6db" - integrity sha512-Ul/hLsadC0SvvShxpne+kq2ebSMcitewlNhrwoXXBvFdCqxJt7Ai1AgMhH7AKBUp06uBeYXThJ2ihTszrkdnYw== +node-pty@0.10.0-beta17: + version "0.10.0-beta17" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta17.tgz#962d4a3f4dc6772385e0cad529c209cef3bc79e6" + integrity sha512-tn7EANQacnAvnOQCImvgag1DL0tVmUoY/1yIZbh3u/BBpvCcGHLZJNn7TXheodRLr6hmGSUS2VbfcUr9p0gOug== dependencies: nan "^2.14.0" From b2a389c93ee3d1648fc95d677b4f8a87b1065e11 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 09:23:39 -0700 Subject: [PATCH 75/98] :lipstick: --- .../common/model/notebookTextModel.ts | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 5039c4b4b59..70a16f18282 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -108,7 +108,7 @@ export class NotebookOperationManager { class DelayedEmitter { constructor( - private readonly _onDidModelChangeProxy: Emitter, + private readonly _onDidChangeContent: Emitter, private readonly _increaseVersion: () => void, private readonly _textModel: NotebookTextModel @@ -118,8 +118,7 @@ class DelayedEmitter { emit(data: { triggerDirty: { value: boolean } | undefined, - cellsChange: { value: { synchronous: boolean, splices: NotebookCellTextModelSplice[] } } | undefined, - modelProxyChange: { value: NotebookTextModelChangedEvent } | undefined, + modelContentChange: { value: NotebookTextModelChangedEvent } | undefined, }) { this._increaseVersion(); @@ -127,10 +126,10 @@ class DelayedEmitter { this._textModel.setDirty(true); } - if (data.modelProxyChange) { - this._onDidModelChangeProxy.fire( + if (data.modelContentChange) { + this._onDidChangeContent.fire( { - ...data.modelProxyChange.value, + ...data.modelContentChange.value, versionId: this._textModel.versionId } ); @@ -147,10 +146,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel private _dirty = false; protected readonly _onDidChangeDirty = this._register(new Emitter()); readonly onDidChangeDirty = this._onDidChangeDirty.event; - private readonly _emitSelections = this._register(new Emitter()); - get emitSelections() { return this._emitSelections.event; } private _onDidChangeContent = this._register(new Emitter()); get onDidChangeContent(): Event { return this._onDidChangeContent.event; } + private readonly _emitSelections = this._register(new Emitter()); + get emitSelections() { return this._emitSelections.event; } private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); cells: NotebookCellTextModel[]; @@ -241,7 +240,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = mainCells[i].onDidChangeContent(() => { this.setDirty(true); this._increaseVersionId(); - // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); }); @@ -364,8 +362,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel // should be deferred this._eventEmitter.emit({ triggerDirty: { value: true }, - cellsChange: { value: { synchronous: synchronous, splices: diffs } }, - modelProxyChange: { + modelContentChange: { value: { kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, @@ -554,8 +551,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._eventEmitter.emit({ triggerDirty: { value: triggerDirtyChange }, - cellsChange: undefined, - modelProxyChange: { + modelContentChange: { value: { kind: NotebookCellsChangeType.ChangeCellMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata, synchronous: true } } }); @@ -569,8 +565,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._eventEmitter.emit({ triggerDirty: { value: !this.transientOptions.transientOutputs }, - cellsChange: undefined, - modelProxyChange: { + modelContentChange: { value: { kind: NotebookCellsChangeType.Output, versionId: this.versionId, From 8b0a7c9582c3f108c18dd6d9f9721e7bcfa8fb56 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 19:56:24 +0200 Subject: [PATCH 76/98] debt - remove _unInitializedDocuments --- .../api/browser/mainThreadNotebook.ts | 8 -- .../workbench/api/common/extHost.protocol.ts | 2 +- .../workbench/api/common/extHostNotebook.ts | 127 +++++++----------- 3 files changed, 51 insertions(+), 86 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index fb62baa61bb..7e9022063e1 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -402,10 +402,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo options, reloadNotebook: async (mainthreadTextModel: NotebookTextModel) => { const data = await this._proxy.$resolveNotebookData(viewType, mainthreadTextModel.uri); - if (!data) { - return; - } - mainthreadTextModel.updateLanguages(data.languages); mainthreadTextModel.metadata = data.metadata; mainthreadTextModel.transientOptions = options; @@ -425,10 +421,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo createNotebook: async (textModel: NotebookTextModel, backupId?: string) => { // open notebook document const data = await this._proxy.$resolveNotebookData(textModel.viewType, textModel.uri, backupId); - if (!data) { - return; - } - textModel.updateLanguages(data.languages); textModel.metadata = data.metadata; textModel.transientOptions = options; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 94a655ceb78..49f22175d18 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1672,7 +1672,7 @@ export interface INotebookDocumentsAndEditorsDelta { } export interface ExtHostNotebookShape { - $resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise; + $resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise; $resolveNotebookEditor(viewType: string, uri: UriComponents, editorId: string): Promise; $provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise; $resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise; diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 91b01a2da4c..46835b397b7 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -904,7 +904,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN private readonly _notebookKernels = new Map(); private readonly _notebookKernelProviders = new Map(); private readonly _documents = new ResourceMap(); - private readonly _unInitializedDocuments = new ResourceMap(); private readonly _editors = new Map(); private readonly _webviewComm = new Map(); private readonly _commandsConverter: CommandsConverter; @@ -1076,49 +1075,24 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN }); } - async $resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise { + async $resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise { const provider = this._notebookContentProviders.get(viewType); - const revivedUri = URI.revive(uri); if (!provider) { - return; + throw new Error(`NO provider for '${viewType}'`); } - const storageRoot = this._extensionStoragePaths.workspaceValue(provider.extension) ?? this._extensionStoragePaths.globalValue(provider.extension); - let document = this._documents.get(revivedUri); - - if (!document) { - const that = this; - document = this._unInitializedDocuments.get(revivedUri) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, { - emitModelChange(event: vscode.NotebookCellsChangeEvent): void { - that._onDidChangeNotebookCells.fire(event); - }, - emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void { - that._onDidChangeCellOutputs.fire(event); - }, - emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void { - that._onDidChangeCellLanguage.fire(event); - }, - emitCellMetadataChange(event: vscode.NotebookCellMetadataChangeEvent): void { - that._onDidChangeCellMetadata.fire(event); - }, - }, viewType, revivedUri, this, storageRoot); - this._unInitializedDocuments.set(revivedUri, document); - } - - const rawCells = await provider.provider.openNotebook(URI.revive(uri), { backupId }); - const dto = { + const data = await provider.provider.openNotebook(URI.revive(uri), { backupId }); + return { metadata: { ...notebookDocumentMetadataDefaults, - ...rawCells.metadata + ...data.metadata }, - languages: rawCells.languages, - cells: rawCells.cells.map(cell => ({ + languages: data.languages, + cells: data.cells.map(cell => ({ ...cell, outputs: cell.outputs.map(o => addIdToOutput(o)) })), }; - - return dto; } async $resolveNotebookEditor(viewType: string, uri: UriComponents, editorId: string): Promise { @@ -1406,64 +1380,63 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN const addedCellDocuments: IModelAddedData[] = []; for (const modelData of delta.addedDocuments) { - const revivedUri = URI.revive(modelData.uri); + const uri = URI.revive(modelData.uri); const viewType = modelData.viewType; const entry = this._notebookContentProviders.get(viewType); const storageRoot = entry && (this._extensionStoragePaths.workspaceValue(entry.extension) ?? this._extensionStoragePaths.globalValue(entry.extension)); + if (this._documents.has(uri)) { + throw new Error(`adding EXISTING notebook ${uri}`); + } + const that = this; - if (!this._documents.has(revivedUri)) { - const that = this; - - const document = this._unInitializedDocuments.get(revivedUri) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, { - emitModelChange(event: vscode.NotebookCellsChangeEvent): void { - that._onDidChangeNotebookCells.fire(event); - }, - emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void { - that._onDidChangeCellOutputs.fire(event); - }, - emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void { - that._onDidChangeCellLanguage.fire(event); - }, - emitCellMetadataChange(event: vscode.NotebookCellMetadataChangeEvent): void { - that._onDidChangeCellMetadata.fire(event); - } - }, viewType, revivedUri, this, storageRoot); - - this._unInitializedDocuments.delete(revivedUri); - if (modelData.metadata) { - document.notebookDocument.metadata = { - ...notebookDocumentMetadataDefaults, - ...modelData.metadata - }; + const document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, { + emitModelChange(event: vscode.NotebookCellsChangeEvent): void { + that._onDidChangeNotebookCells.fire(event); + }, + emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void { + that._onDidChangeCellOutputs.fire(event); + }, + emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void { + that._onDidChangeCellLanguage.fire(event); + }, + emitCellMetadataChange(event: vscode.NotebookCellMetadataChangeEvent): void { + that._onDidChangeCellMetadata.fire(event); } + }, viewType, uri, this, storageRoot); - document.acceptModelChanged({ - kind: NotebookCellsChangeType.Initialize, - versionId: modelData.versionId, - changes: [[ - 0, - 0, - modelData.cells - ]] - }, false); - // add cell document as vscode.TextDocument - addedCellDocuments.push(...modelData.cells.map(cell => ExtHostCell.asModelAddData(document.notebookDocument, cell))); + if (modelData.metadata) { + document.notebookDocument.metadata = { + ...notebookDocumentMetadataDefaults, + ...modelData.metadata + }; + } - this._documents.get(revivedUri)?.dispose(); - this._documents.set(revivedUri, document); + document.acceptModelChanged({ + kind: NotebookCellsChangeType.Initialize, + versionId: modelData.versionId, + changes: [[ + 0, + 0, + modelData.cells + ]] + }, false); - // create editor if populated - if (modelData.attachedEditor) { - this._createExtHostEditor(document, modelData.attachedEditor.id, modelData.attachedEditor.selections, modelData.attachedEditor.visibleRanges); - editorChanged = true; - } + // add cell document as vscode.TextDocument + addedCellDocuments.push(...modelData.cells.map(cell => ExtHostCell.asModelAddData(document.notebookDocument, cell))); + + this._documents.get(uri)?.dispose(); + this._documents.set(uri, document); + + // create editor if populated + if (modelData.attachedEditor) { + this._createExtHostEditor(document, modelData.attachedEditor.id, modelData.attachedEditor.selections, modelData.attachedEditor.visibleRanges); + editorChanged = true; } this._documentsAndEditors.$acceptDocumentsAndEditorsDelta({ addedDocuments: addedCellDocuments }); - const document = this._documents.get(revivedUri)!; this._onDidOpenNotebookDocument.fire(document.notebookDocument); } } From e429fc386e9a202c1a1471b3184b972152dc8ffb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 20:10:28 +0200 Subject: [PATCH 77/98] remove `NotebookDocument#displayOrder` , fixes https://github.com/microsoft/vscode/issues/106305 --- src/vs/vscode.proposed.d.ts | 1 - src/vs/workbench/api/common/extHostNotebook.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 676798f8e07..b0b5547fa83 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1327,7 +1327,6 @@ declare module 'vscode' { readonly isUntitled: boolean; readonly cells: ReadonlyArray; languages: string[]; - displayOrder?: GlobPattern[]; metadata: NotebookDocumentMetadata; } diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 46835b397b7..6998c475a7e 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -215,7 +215,6 @@ export class ExtHostNotebookDocument extends Disposable { private _metadata: Required = notebookDocumentMetadataDefaults; private _metadataChangeListener: IDisposable; - private _displayOrder: string[] = []; private _versionId = 0; private _isDirty: boolean = false; private _backupCounter = 1; @@ -284,8 +283,6 @@ export class ExtHostNotebookDocument extends Disposable { get cells(): ReadonlyArray { return that._cells.map(cell => cell.cell); }, get languages() { return that._languages; }, set languages(value: string[]) { that._trySetLanguages(value); }, - get displayOrder() { return that._displayOrder; }, - set displayOrder(value: string[]) { that._displayOrder = value; }, get metadata() { return that._metadata; }, set metadata(value: Required) { that._updateMetadata(value); }, }); From ed377f963fbb351dca610804d251952e3ab3f7e1 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 11:20:27 -0700 Subject: [PATCH 78/98] no uninitialized documents. --- .../workbench/api/common/extHostNotebook.ts | 42 +------ .../common/model/notebookTextModel.ts | 109 ++++++++++-------- 2 files changed, 66 insertions(+), 85 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 60b09ee72aa..861165d8ed3 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -212,8 +212,7 @@ export class ExtHostNotebookDocument extends Disposable { private _cellDisposableMapping = new Map(); private _notebook: vscode.NotebookDocument | undefined; - - private _metadata: Required = notebookDocumentMetadataDefaults; + private _metadata: Required; private _metadataChangeListener: IDisposable; private _displayOrder: string[] = []; private _versionId = 0; @@ -230,13 +229,14 @@ export class ExtHostNotebookDocument extends Disposable { private readonly _documentsAndEditors: ExtHostDocumentsAndEditors, private readonly _emitter: INotebookEventEmitter, private readonly _viewType: string, + metadata: Required, public readonly uri: URI, public readonly renderingHandler: ExtHostNotebookOutputRenderingHandler, private readonly _storagePath: URI | undefined ) { super(); - const observableMetadata = getObservable(notebookDocumentMetadataDefaults); + const observableMetadata = getObservable(metadata); this._metadata = observableMetadata.proxy; this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => { this._tryUpdateMetadata(); @@ -881,7 +881,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN private readonly _notebookKernels = new Map(); private readonly _notebookKernelProviders = new Map(); private readonly _documents = new ResourceMap(); - private readonly _unInitializedDocuments = new ResourceMap(); private readonly _editors = new Map(); private readonly _webviewComm = new Map(); private readonly _commandsConverter: CommandsConverter; @@ -1058,33 +1057,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN async $resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise { const provider = this._notebookContentProviders.get(viewType); - const revivedUri = URI.revive(uri); if (!provider) { return; } - const storageRoot = this._extensionStoragePaths.workspaceValue(provider.extension) ?? this._extensionStoragePaths.globalValue(provider.extension); - let document = this._documents.get(revivedUri); - - if (!document) { - const that = this; - document = this._unInitializedDocuments.get(revivedUri) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, { - emitModelChange(event: vscode.NotebookCellsChangeEvent): void { - that._onDidChangeNotebookCells.fire(event); - }, - emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void { - that._onDidChangeCellOutputs.fire(event); - }, - emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void { - that._onDidChangeCellLanguage.fire(event); - }, - emitCellMetadataChange(event: vscode.NotebookCellMetadataChangeEvent): void { - that._onDidChangeCellMetadata.fire(event); - }, - }, viewType, revivedUri, this, storageRoot); - this._unInitializedDocuments.set(revivedUri, document); - } - const rawCells = await provider.provider.openNotebook(URI.revive(uri), { backupId }); const dto = { metadata: { @@ -1394,7 +1370,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN if (!this._documents.has(revivedUri)) { const that = this; - const document = this._unInitializedDocuments.get(revivedUri) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, { + const document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, { emitModelChange(event: vscode.NotebookCellsChangeEvent): void { that._onDidChangeNotebookCells.fire(event); }, @@ -1407,15 +1383,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN emitCellMetadataChange(event: vscode.NotebookCellMetadataChangeEvent): void { that._onDidChangeCellMetadata.fire(event); } - }, viewType, revivedUri, this, storageRoot); - - this._unInitializedDocuments.delete(revivedUri); - if (modelData.metadata) { - document.notebookDocument.metadata = { - ...notebookDocumentMetadataDefaults, - ...modelData.metadata - }; - } + }, viewType, { ...notebookDocumentMetadataDefaults, ...modelData.metadata }, revivedUri, this, storageRoot); document.acceptModelChanged({ kind: NotebookCellsChangeType.Initialize, diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 70a16f18282..fbd463ac2f5 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; -import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellTextModelSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ITextSnapshot } from 'vs/editor/common/model'; import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo'; import { InsertCellEdit, DeleteCellEdit, MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit'; @@ -122,8 +122,8 @@ class DelayedEmitter { }) { this._increaseVersion(); - if (data.triggerDirty && data.triggerDirty.value) { - this._textModel.setDirty(true); + if (data.triggerDirty) { + this._textModel.setDirty(data.triggerDirty.value); } if (data.modelContentChange) { @@ -328,11 +328,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._modelService ); const dirtyStateListener = cell.onDidChangeContent(() => { - this.setDirty(true); - this._increaseVersionId(); - // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); - + this._eventEmitter.emit({ + triggerDirty: { value: true }, + modelContentChange: { value: { kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true } } + }); }); this._cellListeners.set(cell.handle, dirtyStateListener); this._mapping.set(cell.handle, cell); @@ -413,9 +412,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel updateNotebookMetadata(metadata: NotebookDocumentMetadata) { this.metadata = metadata; - // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeDocumentMetadata); - this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeDocumentMetadata, versionId: this.versionId, metadata: this.metadata, synchronous: true }); - + this._eventEmitter.emit({ + triggerDirty: { value: true }, + modelContentChange: { value: { kind: NotebookCellsChangeType.ChangeDocumentMetadata, versionId: this.versionId, metadata: this.metadata, synchronous: true } } + }); } insertTemplateCell(cell: NotebookCellTextModel) { @@ -429,14 +429,29 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const dirtyStateListener = cell.onDidChangeContent(() => { this._isUntitled = false; - this.setDirty(true); - this._increaseVersionId(); - // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); - + this._eventEmitter.emit({ + triggerDirty: { value: true }, + modelContentChange: { value: { kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true } } + }); }); this._cellListeners.set(cell.handle, dirtyStateListener); + this.setDirty(false); + + // this._eventEmitter.emit({ + // triggerDirty: undefined, + // modelContentChange: { value: { + // kind: NotebookCellsChangeType.ModelChange, + // versionId: this._versionId, changes: + // [[ + // 0, + // 0, + // [cell] + // ]], + // synchronous: true + // } } + // }); + this.setDirty(false); // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); @@ -460,30 +475,30 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel for (let i = 0; i < cells.length; i++) { this._mapping.set(cells[i].handle, cells[i]); const dirtyStateListener = cells[i].onDidChangeContent(() => { - this.setDirty(true); - this._increaseVersionId(); - // this._onDidChangeContent.fire(NotebookCellsChangeType.ChangeCellContent); - this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true }); + this._eventEmitter.emit({ + triggerDirty: { value: true }, + modelContentChange: { value: { kind: NotebookCellsChangeType.ChangeCellContent, versionId: this.versionId, synchronous: true } } + }); }); this._cellListeners.set(cells[i].handle, dirtyStateListener); } this.cells.splice(index, 0, ...cells); - this.setDirty(true); - // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); - - this._increaseVersionId(); - - this._onDidChangeContent.fire({ - kind: NotebookCellsChangeType.ModelChange, - versionId: this._versionId, changes: - [[ - index, - 0, - cells - ]], - synchronous + this._eventEmitter.emit({ + triggerDirty: { value: true }, + modelContentChange: { + value: { + kind: NotebookCellsChangeType.ModelChange, + versionId: this._versionId, changes: + [[ + index, + 0, + cells + ]], + synchronous + } + } }); return; @@ -498,11 +513,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this._cellListeners.delete(cell.handle); } this.cells.splice(index, count); - this.setDirty(true); - // this._onDidChangeContent.fire(NotebookCellsChangeType.ModelChange); - - this._increaseVersionId(); - this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous }); + this._eventEmitter.emit({ + triggerDirty: { value: true }, + modelContentChange: { value: { kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous } } + }); } private _isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata) { @@ -593,8 +607,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel if (cell && cell.language !== languageId) { cell.language = languageId; - this._increaseVersionId(); - this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this.cells.indexOf(cell), language: languageId, synchronous: true }); + this._eventEmitter.emit({ + triggerDirty: undefined, + modelContentChange: { value: { kind: NotebookCellsChangeType.ChangeLanguage, versionId: this._versionId, index: this.cells.indexOf(cell), language: languageId, synchronous: true } } + }); } } @@ -646,17 +662,14 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel { const cells = this.cells.splice(index, length); this.cells.splice(newIdx, 0, ...cells); - this.setDirty(true); - // this._onDidChangeContent.fire(NotebookCellsChangeType.Move); - - this._increaseVersionId(); - this._onDidChangeContent.fire({ kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous }); + this._eventEmitter.emit({ + triggerDirty: { value: true }, + modelContentChange: { value: { kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous } } + }); } // todo, we can't emit this change as it will create a new view model and that will hold // a new reference to the document, thus - // this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[index, length, []]] }); - // this._onDidChangeCells.fire({ synchronous: synchronous, splices: [[newIdx, 0, cells]] }); if (endSelections) { this._emitSelections.fire(endSelections); } From 62f1bf8c6bacd26dd7c3b8e2360d4728f2a26450 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 8 Sep 2020 20:32:26 +0200 Subject: [PATCH 79/98] chore - update references viewlet --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index 30a7f0708ea..7651fc50bb5 100644 --- a/product.json +++ b/product.json @@ -61,7 +61,7 @@ }, { "name": "ms-vscode.references-view", - "version": "0.0.62", + "version": "0.0.63", "repo": "https://github.com/Microsoft/vscode-reference-view", "metadata": { "id": "dc489f46-520d-4556-ae85-1f9eab3c412d", From 76e45c2b69d5eee655500ae21880319e7792d4d4 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Tue, 8 Sep 2020 11:52:54 -0700 Subject: [PATCH 80/98] debug: make serverReadyAction play nicely with js-debug Fixes https://github.com/microsoft/vscode/issues/86035 Fixes https://github.com/microsoft/vscode-js-debug/issues/440 --- .../debug-server-ready/src/extension.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/extensions/debug-server-ready/src/extension.ts b/extensions/debug-server-ready/src/extension.ts index 91e996d665b..9f8737f307f 100644 --- a/extensions/debug-server-ready/src/extension.ts +++ b/extensions/debug-server-ready/src/extension.ts @@ -146,18 +146,13 @@ class ServerReadyDetector extends vscode.Disposable { break; case 'debugWithChrome': - if (vscode.env.remoteName === 'wsl' || !!vscode.extensions.getExtension('msjsdiag.debugger-for-chrome')) { - vscode.debug.startDebugging(session.workspaceFolder, { - type: 'chrome', - name: 'Chrome Debug', - request: 'launch', - url: uri, - webRoot: args.webRoot || WEB_ROOT - }, session); - } else { - const errMsg = localize('server.ready.chrome.not.installed', "The action '{0}' requires the '{1}' extension.", 'debugWithChrome', 'Debugger for Chrome'); - vscode.window.showErrorMessage(errMsg, { modal: true }).then(_ => undefined); - } + vscode.debug.startDebugging(session.workspaceFolder, { + type: 'pwa-chrome', + name: 'Chrome Debug', + request: 'launch', + url: uri, + webRoot: args.webRoot || WEB_ROOT + }); break; default: From baef0ae22b66f7a29bf4a9b102901ac1f3279bc9 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Sep 2020 21:04:00 +0200 Subject: [PATCH 81/98] high contrast switching in browser --- .../electron-sandbox/desktop.contribution.ts | 9 +------- .../browser/browserHostColorSchemeService.ts | 7 ++++++- .../themes/browser/workbenchThemeService.ts | 1 + .../themes/common/themeConfiguration.ts | 21 +++++++++++++++++-- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/electron-sandbox/desktop.contribution.ts b/src/vs/workbench/electron-sandbox/desktop.contribution.ts index 07fe262c796..693ea6bcae0 100644 --- a/src/vs/workbench/electron-sandbox/desktop.contribution.ts +++ b/src/vs/workbench/electron-sandbox/desktop.contribution.ts @@ -9,7 +9,7 @@ import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/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 { isLinux, isMacintosh } from 'vs/base/common/platform'; 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'; @@ -255,13 +255,6 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema'; 'default': false, 'description': nls.localize('closeWhenEmpty', "Controls whether closing the last editor should also close the window. This setting only applies for windows that do not show folders.") }, - 'window.autoDetectHighContrast': { - 'type': 'boolean', - 'default': true, - 'description': nls.localize('autoDetectHighContrast', "If enabled, will automatically change to high contrast theme if the OS is using a high contrast theme, and to dark theme when switching away from a high contrast theme."), - 'scope': ConfigurationScope.APPLICATION, - 'included': isWindows || isMacintosh - }, 'window.doubleClickIconToClose': { 'type': 'boolean', 'default': false, diff --git a/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts index 2f16e857fc7..086043eb041 100644 --- a/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts +++ b/src/vs/workbench/services/themes/browser/browserHostColorSchemeService.ts @@ -29,6 +29,9 @@ export class BrowserHostColorSchemeService extends Disposable implements IHostCo window.matchMedia('(prefers-color-scheme: dark)').addListener(() => { this._onDidSchemeChangeEvent.fire(); }); + window.matchMedia('(forced-colors: active)').addListener(() => { + this._onDidSchemeChangeEvent.fire(); + }); } get onDidChangeColorScheme(): Event { @@ -36,7 +39,9 @@ export class BrowserHostColorSchemeService extends Disposable implements IHostCo } get colorScheme(): ColorScheme { - if (window.matchMedia(`(prefers-color-scheme: light)`).matches) { + if (window.matchMedia(`(forced-colors: active)`).matches) { + return ColorScheme.HIGH_CONTRAST; + } else if (window.matchMedia(`(prefers-color-scheme: light)`).matches) { return ColorScheme.LIGHT; } else if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) { return ColorScheme.DARK; diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index 7aa072ca36e..39c18b0c7d3 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -438,6 +438,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { } } }; + ruleCollector.addRule(`.monaco-workbench { forced-color-adjust: none; }`); themingRegistry.getThemingParticipants().forEach(p => p(themeData, ruleCollector, this.environmentService)); _applyRules([...cssRules].join('\n'), colorThemeRulesClassName); } diff --git a/src/vs/workbench/services/themes/common/themeConfiguration.ts b/src/vs/workbench/services/themes/common/themeConfiguration.ts index cd4ad6203f5..795b03edf96 100644 --- a/src/vs/workbench/services/themes/common/themeConfiguration.ts +++ b/src/vs/workbench/services/themes/common/themeConfiguration.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import * as types from 'vs/base/common/types'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationNode, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { textmateColorsSchemaId, textmateColorGroupSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema'; @@ -96,6 +96,13 @@ const productIconThemeSettingSchema: IConfigurationPropertySchema = { errorMessage: nls.localize('productIconThemeError', "Product icon theme is unknown or not installed.") }; +const detectHCSchemeSettingSchema: IConfigurationPropertySchema = { + type: 'boolean', + default: true, + description: nls.localize('autoDetectHighContrast', "If enabled, will automatically change to high contrast theme if the OS is using a high contrast theme."), + scope: ConfigurationScope.APPLICATION +}; + const themeSettingsConfiguration: IConfigurationNode = { id: 'workbench', order: 7.1, @@ -105,7 +112,6 @@ const themeSettingsConfiguration: IConfigurationNode = { [ThemeSettings.PREFERRED_DARK_THEME]: preferredDarkThemeSettingSchema, [ThemeSettings.PREFERRED_LIGHT_THEME]: preferredLightThemeSettingSchema, [ThemeSettings.PREFERRED_HC_THEME]: preferredHCThemeSettingSchema, - [ThemeSettings.DETECT_COLOR_SCHEME]: detectColorSchemeSettingSchema, [ThemeSettings.FILE_ICON_THEME]: fileIconThemeSettingSchema, [ThemeSettings.COLOR_CUSTOMIZATIONS]: colorCustomizationsSchema, [ThemeSettings.PRODUCT_ICON_THEME]: productIconThemeSettingSchema @@ -113,6 +119,17 @@ const themeSettingsConfiguration: IConfigurationNode = { }; configurationRegistry.registerConfiguration(themeSettingsConfiguration); +const themeSettingsWindowConfiguration: IConfigurationNode = { + id: 'window', + order: 8.1, + type: 'object', + properties: { + [ThemeSettings.DETECT_HC]: detectHCSchemeSettingSchema, + [ThemeSettings.DETECT_COLOR_SCHEME]: detectColorSchemeSettingSchema, + } +}; +configurationRegistry.registerConfiguration(themeSettingsWindowConfiguration); + function tokenGroupSettings(description: string): IJSONSchema { return { description, From 7248c9ac80370f024988fdbcd10b4f5b3b581da2 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 8 Sep 2020 14:05:59 -0500 Subject: [PATCH 82/98] Fix occasional bad custom selectbox layout Fix #106302 --- .../browser/ui/selectBox/selectBoxCustom.ts | 38 ++++--------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index a8f9bb24c5a..1d29e9a3c00 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -503,42 +503,15 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi // Iterate over detailed descriptions, find max height private measureMaxDetailsHeight(): number { - let maxDetailsPaneHeight = 0; - this.options.forEach((option, index) => { - - this.selectionDetailsPane.innerText = ''; - - if (option.description) { - if (option.descriptionIsMarkdown) { - this.selectionDetailsPane.appendChild(this.renderDescriptionMarkdown(option.description)); - } else { - this.selectionDetailsPane.innerText = option.description; - } - this.selectionDetailsPane.style.display = 'block'; - } else { - this.selectionDetailsPane.style.display = 'none'; - } + this.options.forEach((_option, index) => { + this.updateDetail(index); if (this.selectionDetailsPane.offsetHeight > maxDetailsPaneHeight) { maxDetailsPaneHeight = this.selectionDetailsPane.offsetHeight; } }); - // Reset description to selected - - this.selectionDetailsPane.innerText = ''; - const description = this.options[this.selected].description || null; - const descriptionIsMarkdown = this.options[this.selected].descriptionIsMarkdown || null; - - if (description) { - if (descriptionIsMarkdown) { - this.selectionDetailsPane.appendChild(this.renderDescriptionMarkdown(description)); - } else { - this.selectionDetailsPane.innerText = description; - } - this.selectionDetailsPane.style.display = 'block'; - } return maxDetailsPaneHeight; } @@ -676,6 +649,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi this.selectDropDownContainer.style.height = (listHeight + verticalPadding) + 'px'; } + this.updateDetail(this.selected); + this.selectDropDownContainer.style.width = selectOptimalWidth; // Maintain focus outline on parent select as well as list container - tabindex for focus @@ -870,8 +845,11 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi return; } + this.updateDetail(e.indexes[0]); + } + + private updateDetail(selectedIndex: number): void { this.selectionDetailsPane.innerText = ''; - const selectedIndex = e.indexes[0]; const description = this.options[selectedIndex].description; const descriptionIsMarkdown = this.options[selectedIndex].descriptionIsMarkdown; From 73f84d68c50e186f503dd56ac2827c2d43be731e Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 8 Sep 2020 21:15:35 +0200 Subject: [PATCH 83/98] review comments --- .../platform/electron/electron-main/electronMainService.ts | 2 +- src/vs/platform/theme/common/theme.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 21a2549ef51..acde70fb201 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -46,7 +46,7 @@ export class ElectronMainService implements IElectronMainService { // Color Scheme changes nativeTheme.on('updated', () => { - let colorScheme; + let colorScheme: ColorScheme; if (nativeTheme.shouldUseInvertedColorScheme || nativeTheme.shouldUseHighContrastColors) { colorScheme = ColorScheme.HIGH_CONTRAST; } else if (nativeTheme.shouldUseDarkColors) { diff --git a/src/vs/platform/theme/common/theme.ts b/src/vs/platform/theme/common/theme.ts index 843210bfeb5..90cef457b57 100644 --- a/src/vs/platform/theme/common/theme.ts +++ b/src/vs/platform/theme/common/theme.ts @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ /** - * Color theme used by the OS and by color themes. + * Color scheme used by the OS and by color themes. */ export enum ColorScheme { DARK = 'dark', LIGHT = 'light', HIGH_CONTRAST = 'hc' } - - - From c3018ad2c3de6facd40337f42036e491a52b53bf Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 8 Sep 2020 14:30:31 -0500 Subject: [PATCH 84/98] Bump vscode-ripgrep for ARM #6442 --- package.json | 2 +- remote/package.json | 2 +- remote/yarn.lock | 8 ++++---- yarn.lock | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 92cfce98287..904a6936649 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "vscode-nsfw": "1.2.8", "vscode-oniguruma": "1.3.1", "vscode-proxy-agent": "^0.5.2", - "vscode-ripgrep": "^1.8.0", + "vscode-ripgrep": "^1.9.0", "vscode-sqlite3": "4.0.10", "vscode-textmate": "5.2.0", "xterm": "4.9.0-beta.32", diff --git a/remote/package.json b/remote/package.json index 3b733672a3e..0a7b6f7e0a1 100644 --- a/remote/package.json +++ b/remote/package.json @@ -18,7 +18,7 @@ "vscode-nsfw": "1.2.8", "vscode-oniguruma": "1.3.1", "vscode-proxy-agent": "^0.5.2", - "vscode-ripgrep": "^1.8.0", + "vscode-ripgrep": "^1.9.0", "vscode-textmate": "5.2.0", "xterm": "4.9.0-beta.32", "xterm-addon-search": "0.7.0", diff --git a/remote/yarn.lock b/remote/yarn.lock index 2dfcb19abc6..c5f19e6bbc9 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -410,10 +410,10 @@ vscode-proxy-agent@^0.5.2: https-proxy-agent "^2.2.3" socks-proxy-agent "^4.0.1" -vscode-ripgrep@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.8.0.tgz#dfe7c2ae2a2032df8a8108765c2feef73474888a" - integrity sha512-/Q5XtePkTLLi8yplr5ai24pVEymRF62xH9xXrtj35GTaDCJg3zq1s1/L1UqhVbfNDv4OcMBYjyIAt/quEi3d5w== +vscode-ripgrep@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.9.0.tgz#d6cdea4d290f3c2919472cdcfe2440d5fb1f99db" + integrity sha512-7jyAC/NNfvMPZgCVkyqIn0STYJ7wIk3PF2qA2cX1sEutx1g/e2VtgKAodXnfpreJq4993JT/BSIigOv/0lBSzg== dependencies: https-proxy-agent "^4.0.0" proxy-from-env "^1.1.0" diff --git a/yarn.lock b/yarn.lock index 7712ff05454..774e959c57b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9724,10 +9724,10 @@ vscode-proxy-agent@^0.5.2: https-proxy-agent "^2.2.3" socks-proxy-agent "^4.0.1" -vscode-ripgrep@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.8.0.tgz#dfe7c2ae2a2032df8a8108765c2feef73474888a" - integrity sha512-/Q5XtePkTLLi8yplr5ai24pVEymRF62xH9xXrtj35GTaDCJg3zq1s1/L1UqhVbfNDv4OcMBYjyIAt/quEi3d5w== +vscode-ripgrep@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.9.0.tgz#d6cdea4d290f3c2919472cdcfe2440d5fb1f99db" + integrity sha512-7jyAC/NNfvMPZgCVkyqIn0STYJ7wIk3PF2qA2cX1sEutx1g/e2VtgKAodXnfpreJq4993JT/BSIigOv/0lBSzg== dependencies: https-proxy-agent "^4.0.0" proxy-from-env "^1.1.0" From f63ceed2b004502fffcdf40643aa4a9761a38abe Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Sep 2020 13:42:48 -0700 Subject: [PATCH 85/98] Revert more specific class names for editor tokens Reverts #103485 Fixes #106261 I believe that #103485 broke cases where the markdown renderer creates tokenized strings that are used outside of an editor's dom node (such as in hovers or in webviews) The safest fix for now is to revert it. We can revist this and make the markdown renderer handle the tokenized output better next iteration --- src/vs/editor/common/modes/supports/tokenization.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/modes/supports/tokenization.ts b/src/vs/editor/common/modes/supports/tokenization.ts index e701b60f0a9..12566c3b00e 100644 --- a/src/vs/editor/common/modes/supports/tokenization.ts +++ b/src/vs/editor/common/modes/supports/tokenization.ts @@ -399,10 +399,10 @@ export function generateTokensCSSForColorMap(colorMap: Color[]): string { let rules: string[] = []; for (let i = 1, len = colorMap.length; i < len; i++) { let color = colorMap[i]; - rules[i] = `.monaco-editor .mtk${i} { color: ${color}; }`; + rules[i] = `.mtk${i} { color: ${color}; }`; } - rules.push('.monaco-editor .mtki { font-style: italic; }'); - rules.push('.monaco-editor .mtkb { font-weight: bold; }'); - rules.push('.monaco-editor .mtku { text-decoration: underline; text-underline-position: under; }'); + rules.push('.mtki { font-style: italic; }'); + rules.push('.mtkb { font-weight: bold; }'); + rules.push('.mtku { text-decoration: underline; text-underline-position: under; }'); return rules.join('\n'); } From 6485f44708575cc216587b66660e8d69b099f8ed Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 13:54:31 -0700 Subject: [PATCH 86/98] remove emit selections. --- .../notebook/browser/viewModel/cellEdit.ts | 13 ++--- .../browser/viewModel/notebookViewModel.ts | 13 ++--- .../contrib/notebook/common/model/cellEdit.ts | 47 ++++------------ .../common/model/notebookTextModel.ts | 55 ++++++------------- .../contrib/notebook/common/notebookCommon.ts | 2 +- 5 files changed, 36 insertions(+), 94 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts index 709c41859b2..aac728c93f2 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/cellEdit.ts @@ -52,12 +52,10 @@ export class JoinCellEdit implements IResourceUndoRedoElement { const cell = this.editingDelegate.createCellViewModel(this._deletedRawCell); if (this.direction === 'above') { - this.editingDelegate.insertCell(this.index, this._deletedRawCell); - this.editingDelegate.emitSelections([cell.handle]); + this.editingDelegate.insertCell(this.index, this._deletedRawCell, [cell.handle]); cell.focusMode = CellFocusMode.Editor; } else { - this.editingDelegate.insertCell(this.index, cell.model); - this.editingDelegate.emitSelections([this.cell.handle]); + this.editingDelegate.insertCell(this.index, cell.model, [this.cell.handle]); this.cell.focusMode = CellFocusMode.Editor; } } @@ -72,8 +70,7 @@ export class JoinCellEdit implements IResourceUndoRedoElement { { range: this.inverseRange, text: this.insertContent } ]); - this.editingDelegate.deleteCell(this.index); - this.editingDelegate.emitSelections([this.cell.handle]); + this.editingDelegate.deleteCell(this.index, [this.cell.handle]); this.cell.focusMode = CellFocusMode.Editor; } } @@ -110,10 +107,9 @@ export class SplitCellEdit implements IResourceUndoRedoElement { this.cell.setSelections(this.selections); for (let j = 1; j < this.cellContents.length; j++) { - this.editingDelegate.deleteCell(this.index + 1); + this.editingDelegate.deleteCell(this.index + 1, j === this.cellContents.length - 1 ? [this.cell.handle] : undefined); } - this.editingDelegate.emitSelections([this.cell.handle]); this.cell.focusMode = CellFocusMode.Editor; } @@ -134,7 +130,6 @@ export class SplitCellEdit implements IResourceUndoRedoElement { } if (lastCell) { - this.editingDelegate.emitSelections([lastCell.handle]); lastCell.focusMode = CellFocusMode.Editor; } } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 77739cea9ed..575ea409524 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -327,13 +327,10 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD if (e.kind === NotebookCellsChangeType.ChangeDocumentMetadata) { this.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]); } - })); - this._register(this._notebook.emitSelections(selections => { - // text model emit selection change (for example, undo/redo) - // we should update the selection handle wisely - // TODO, if the editor is note selected, undo/redo should not change the focused element selection - this.updateSelectionsFromEdits(selections); + if (e.endSelections) { + this.updateSelectionsFromEdits(e.endSelections); + } })); this._register(this.eventDispatcher.onDidChangeLayout((e) => { @@ -849,7 +846,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD insertContent, cell, { - insertCell: (index: number, cell: NotebookCellTextModel) => { + insertCell: (index: number, cell: NotebookCellTextModel, endSelections?: number[]) => { this.insertCell(index, cell, true, false); }, deleteCell: (index: number) => { @@ -903,7 +900,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD insertContent, below, { - insertCell: (index: number, cell: NotebookCellTextModel) => { + insertCell: (index: number, cell: NotebookCellTextModel, endSelections?: number[]) => { this.insertCell(index, cell, true, false); }, deleteCell: (index: number) => { diff --git a/src/vs/workbench/contrib/notebook/common/model/cellEdit.ts b/src/vs/workbench/contrib/notebook/common/model/cellEdit.ts index 5cde6b3bfaa..9a9c8c2a3d6 100644 --- a/src/vs/workbench/contrib/notebook/common/model/cellEdit.ts +++ b/src/vs/workbench/contrib/notebook/common/model/cellEdit.ts @@ -12,11 +12,10 @@ import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/noteb * It should not modify Undo/Redo stack */ export interface ITextCellEditingDelegate { - insertCell?(index: number, cell: NotebookCellTextModel): void; - deleteCell?(index: number): void; + insertCell?(index: number, cell: NotebookCellTextModel, endSelections?: number[]): void; + deleteCell?(index: number, endSelections?: number[]): void; moveCell?(fromIndex: number, length: number, toIndex: number, beforeSelections: number[] | undefined, endSelections: number[] | undefined): void; updateCellMetadata?(index: number, newMetadata: NotebookCellMetadata): void; - emitSelections(selections: number[]): void; } @@ -38,20 +37,14 @@ export class InsertCellEdit implements IResourceUndoRedoElement { throw new Error('Notebook Delete Cell not implemented for Undo/Redo'); } - this.editingDelegate.deleteCell(this.insertIndex); - if (this.beforedSelections) { - this.editingDelegate.emitSelections(this.beforedSelections); - } + this.editingDelegate.deleteCell(this.insertIndex, this.beforedSelections); } redo(): void { if (!this.editingDelegate.insertCell) { throw new Error('Notebook Insert Cell not implemented for Undo/Redo'); } - this.editingDelegate.insertCell(this.insertIndex, this.cell); - if (this.endSelections) { - this.editingDelegate.emitSelections(this.endSelections); - } + this.editingDelegate.insertCell(this.insertIndex, this.cell, this.endSelections); } } @@ -77,10 +70,7 @@ export class DeleteCellEdit implements IResourceUndoRedoElement { throw new Error('Notebook Insert Cell not implemented for Undo/Redo'); } - this.editingDelegate.insertCell(this.insertIndex, this._cell); - if (this.beforedSelections) { - this.editingDelegate.emitSelections(this.beforedSelections); - } + this.editingDelegate.insertCell(this.insertIndex, this._cell, this.beforedSelections); } redo(): void { @@ -88,10 +78,7 @@ export class DeleteCellEdit implements IResourceUndoRedoElement { throw new Error('Notebook Delete Cell not implemented for Undo/Redo'); } - this.editingDelegate.deleteCell(this.insertIndex); - if (this.endSelections) { - this.editingDelegate.emitSelections(this.endSelections); - } + this.editingDelegate.deleteCell(this.insertIndex, this.endSelections); } } @@ -116,9 +103,6 @@ export class MoveCellEdit implements IResourceUndoRedoElement { } this.editingDelegate.moveCell(this.toIndex, this.length, this.fromIndex, this.endSelections, this.beforedSelections); - if (this.beforedSelections) { - this.editingDelegate.emitSelections(this.beforedSelections); - } } redo(): void { @@ -127,9 +111,6 @@ export class MoveCellEdit implements IResourceUndoRedoElement { } this.editingDelegate.moveCell(this.fromIndex, this.length, this.toIndex, this.beforedSelections, this.endSelections); - if (this.endSelections) { - this.editingDelegate.emitSelections(this.endSelections); - } } } @@ -152,17 +133,13 @@ export class SpliceCellsEdit implements IResourceUndoRedoElement { this.diffs.forEach(diff => { for (let i = 0; i < diff[2].length; i++) { - this.editingDelegate.deleteCell!(diff[0]); + this.editingDelegate.deleteCell!(diff[0], this.beforeHandles); } diff[1].reverse().forEach(cell => { - this.editingDelegate.insertCell!(diff[0], cell); + this.editingDelegate.insertCell!(diff[0], cell, this.beforeHandles); }); }); - - if (this.beforeHandles) { - this.editingDelegate.emitSelections(this.beforeHandles); - } } redo(): void { @@ -172,17 +149,13 @@ export class SpliceCellsEdit implements IResourceUndoRedoElement { this.diffs.reverse().forEach(diff => { for (let i = 0; i < diff[1].length; i++) { - this.editingDelegate.deleteCell!(diff[0]); + this.editingDelegate.deleteCell!(diff[0], this.endHandles); } diff[2].reverse().forEach(cell => { - this.editingDelegate.insertCell!(diff[0], cell); + this.editingDelegate.insertCell!(diff[0], cell, this.endHandles); }); }); - - if (this.endHandles) { - this.editingDelegate.emitSelections(this.endHandles); - } } } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index fbd463ac2f5..c90b406d1e3 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -148,8 +148,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel readonly onDidChangeDirty = this._onDidChangeDirty.event; private _onDidChangeContent = this._register(new Emitter()); get onDidChangeContent(): Event { return this._onDidChangeContent.event; } - private readonly _emitSelections = this._register(new Emitter()); - get emitSelections() { return this._emitSelections.event; } private _mapping: Map = new Map(); private _cellListeners: Map = new Map(); cells: NotebookCellTextModel[]; @@ -353,9 +351,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel }); this._operationManager.pushEditOperation(new SpliceCellsEdit(this.uri, undoDiff, { - insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, - deleteCell: (index) => { this._removeCell(index, 1, true); }, - emitSelections: (selections) => { this._emitSelections.fire(selections); } + insertCell: (index, cell, endSelections?: number[]) => { this._insertNewCell(index, [cell], true, endSelections); }, + deleteCell: (index, endSelections?: number[]) => { this._removeCell(index, 1, true, endSelections); }, }, undefined, undefined)); // should be deferred @@ -469,7 +466,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } - private _insertNewCell(index: number, cells: NotebookCellTextModel[], synchronous: boolean): void { + private _insertNewCell(index: number, cells: NotebookCellTextModel[], synchronous: boolean, endSelections?: number[]): void { this._isUntitled = false; for (let i = 0; i < cells.length; i++) { @@ -496,7 +493,8 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel 0, cells ]], - synchronous + synchronous, + endSelections: endSelections } } }); @@ -504,7 +502,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } - private _removeCell(index: number, count: number, synchronous: boolean) { + private _removeCell(index: number, count: number, synchronous: boolean, endSelections?: number[]) { this._isUntitled = false; for (let i = index; i < index + count; i++) { @@ -515,7 +513,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.cells.splice(index, count); this._eventEmitter.emit({ triggerDirty: { value: true }, - modelContentChange: { value: { kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous } } + modelContentChange: { value: { kind: NotebookCellsChangeType.ModelChange, versionId: this._versionId, changes: [[index, count, []]], synchronous, endSelections } } }); } @@ -553,8 +551,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return; } this._changeCellMetadata(cell.handle, newMetadata, false); - }, - emitSelections: (selections) => { this._emitSelections.fire(selections); } + } })); } // should be deferred @@ -617,33 +614,24 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel insertCell(index: number, cell: NotebookCellTextModel, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): void { if (pushUndoStop) { this._operationManager.pushEditOperation(new InsertCellEdit(this.uri, index, cell, { - insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, - deleteCell: (index) => { this._removeCell(index, 1, true); }, - emitSelections: (selections) => { this._emitSelections.fire(selections); } + insertCell: (index, cell, endSelections) => { this._insertNewCell(index, [cell], true, endSelections); }, + deleteCell: (index, endSelections) => { this._removeCell(index, 1, true, endSelections); }, }, beforeSelections, endSelections)); } - this._insertNewCell(index, [cell], synchronous); - - if (endSelections) { - this._emitSelections.fire(endSelections); - } + this._insertNewCell(index, [cell], synchronous, endSelections); } deleteCell(index: number, synchronous: boolean, pushUndoStop: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined) { const cell = this.cells[index]; if (pushUndoStop) { this._operationManager.pushEditOperation(new DeleteCellEdit(this.uri, index, cell, { - insertCell: (index, cell) => { this._insertNewCell(index, [cell], true); }, - deleteCell: (index) => { this._removeCell(index, 1, true); }, - emitSelections: (selections) => { this._emitSelections.fire(selections); } + insertCell: (index, cell, endSelections) => { this._insertNewCell(index, [cell], true, endSelections); }, + deleteCell: (index, endSelections) => { this._removeCell(index, 1, true, endSelections); }, }, beforeSelections, endSelections)); } - this._removeCell(index, 1, synchronous); - if (endSelections) { - this._emitSelections.fire(endSelections); - } + this._removeCell(index, 1, synchronous, endSelections); } moveCellToIdx(index: number, length: number, newIdx: number, synchronous: boolean, pushedToUndoStack: boolean, beforeSelections: number[] | undefined, endSelections: number[] | undefined): boolean { @@ -652,7 +640,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel moveCell: (fromIndex: number, length: number, toIndex: number, beforeSelections: number[] | undefined, endSelections: number[] | undefined) => { this.moveCellToIdx(fromIndex, length, toIndex, true, false, beforeSelections, endSelections); }, - emitSelections: (selections) => { this._emitSelections.fire(selections); } }, beforeSelections, endSelections)); } @@ -664,16 +651,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel this.cells.splice(newIdx, 0, ...cells); this._eventEmitter.emit({ triggerDirty: { value: true }, - modelContentChange: { value: { kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous } } + modelContentChange: { value: { kind: NotebookCellsChangeType.Move, versionId: this._versionId, index, length, newIdx, cells, synchronous, endSelections } } }); } - // todo, we can't emit this change as it will create a new view model and that will hold - // a new reference to the document, thus - if (endSelections) { - this._emitSelections.fire(endSelections); - } - return true; } @@ -696,13 +677,9 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const newCells = []; for (let j = 1; j < newLinesContents.length; j++, insertIndex++) { const cell = this.createCellTextModel(newLinesContents[j], language, kind, [], undefined); - this.insertCell(insertIndex, cell, true, false, undefined, undefined); + this.insertCell(insertIndex, cell, true, false, undefined, j === newLinesContents.length - 1 ? endSelections : undefined); newCells.push(cell); } - - if (endSelections) { - this._emitSelections.fire(endSelections); - } } //#endregion diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 38f03cb2b81..9e6f00885d4 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -407,7 +407,7 @@ export interface NotebookDocumentChangeMetadataEvent { } export type NotebookCellsChangedEventDto = NotebookCellsInitializeEvent | NotebookDocumentChangeMetadataEvent | NotebookCellContentChangeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent; -export type NotebookTextModelChangedEvent = (NotebookCellsInitializeEvent | NotebookDocumentChangeMetadataEvent | NotebookCellContentChangeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent) & { synchronous: boolean; }; +export type NotebookTextModelChangedEvent = (NotebookCellsInitializeEvent | NotebookDocumentChangeMetadataEvent | NotebookCellContentChangeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookOutputChangedEvent | NotebookCellsChangeLanguageEvent | NotebookCellsChangeMetadataEvent) & { synchronous: boolean; endSelections?: number[] }; export const enum CellEditType { Replace = 1, From ccc6fe63abbd1facfa55b352755e0ba00a356f74 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 14:13:22 -0700 Subject: [PATCH 87/98] merge conflict resolve. --- .../notebook/browser/viewModel/notebookViewModel.ts | 9 --------- .../contrib/notebook/common/model/notebookTextModel.ts | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 5151d3adc2f..4553fdd0412 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -771,9 +771,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD }, deleteCell: (index: number) => { this.deleteCell(index, true, false); - }, - emitSelections: (selections: number[]) => { - this.updateSelectionsFromEdits(selections); } } )); @@ -850,9 +847,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD }, createCellViewModel: (cell: NotebookCellTextModel) => { return createCellViewModel(this._instantiationService, this, cell); - }, - emitSelections: (selections: number[]) => { - this.updateSelectionsFromEdits(selections); } }) ); @@ -904,9 +898,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD }, createCellViewModel: (cell: NotebookCellTextModel) => { return createCellViewModel(this._instantiationService, this, cell); - }, - emitSelections: (selections: number[]) => { - this.updateSelectionsFromEdits(selections); } }) ); diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 9cfc7aad971..5537f5d9f15 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; -import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, NotebookCellTextModelSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ITextSnapshot } from 'vs/editor/common/model'; import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo'; import { InsertCellEdit, DeleteCellEdit, MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit'; From f48b0f4672079e1866748bffed3a39a7613432f8 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 8 Sep 2020 14:18:34 -0700 Subject: [PATCH 88/98] fix integration tests. --- src/vs/workbench/api/common/extHostNotebook.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 583e05dcd40..03e7cedad80 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -1378,14 +1378,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN } }, viewType, { ...notebookDocumentMetadataDefaults, ...modelData.metadata }, uri, this, storageRoot); - - if (modelData.metadata) { - document.notebookDocument.metadata = { - ...notebookDocumentMetadataDefaults, - ...modelData.metadata - }; - } - document.acceptModelChanged({ kind: NotebookCellsChangeType.Initialize, versionId: modelData.versionId, From e969bc18a13d4b5692b10d227cdaab185d0d9200 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Sep 2020 14:39:58 -0700 Subject: [PATCH 89/98] Disable errors in non-semantic supported files Fixes #106299 Fixes #106314 Also enables js/ts features on the right side of PRs and in search results --- .../src/tsServer/bufferSyncSupport.ts | 7 +++++-- .../src/typescriptService.ts | 7 ++++++- .../src/typescriptServiceClient.ts | 20 +++++++++++++++++++ .../src/utils/fileSchemes.ts | 6 +----- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts b/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts index fdc552a293c..40610b66f11 100644 --- a/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts +++ b/extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts @@ -306,7 +306,10 @@ class GetErrRequest { public readonly files: ResourceMap, onDone: () => void ) { - const allFiles = coalesce(Array.from(files.entries).map(entry => client.normalizedPath(entry.resource))); + const allFiles = coalesce(Array.from(files.entries) + .filter(entry => client.hasCapabilityForResource(entry.resource, ClientCapability.Semantic)) + .map(entry => client.normalizedPath(entry.resource))); + if (!allFiles.length || !client.capabilities.has(ClientCapability.Semantic)) { this._done = true; setImmediate(onDone); @@ -529,7 +532,7 @@ export default class BufferSyncSupport extends Disposable { this.triggerDiagnostics(); } - public getErr(resources: vscode.Uri[]): any { + public getErr(resources: readonly vscode.Uri[]): any { const handledResources = resources.filter(resource => this.handles(resource)); if (!handledResources.length) { return; diff --git a/extensions/typescript-language-features/src/typescriptService.ts b/extensions/typescript-language-features/src/typescriptService.ts index 8a59d97105c..58a78ad19b5 100644 --- a/extensions/typescript-language-features/src/typescriptService.ts +++ b/extensions/typescript-language-features/src/typescriptService.ts @@ -145,10 +145,15 @@ export interface ITypeScriptServiceClient { /** * Tries to ensure that a vscode document is open on the TS server. * - * Returns the normalized path. + * @return The normalized path or `undefined` if the document is not open on the server. */ toOpenedFilePath(document: vscode.TextDocument): string | undefined; + /** + * Checks if `resource` has a given capability. + */ + hasCapabilityForResource(resource: vscode.Uri, capability: ClientCapability): boolean; + getWorkspaceRootForResource(resource: vscode.Uri): string | undefined; readonly onTsServerStarted: vscode.Event<{ version: TypeScriptVersion, usedApiVersion: API }>; diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index a9e6bf10d7f..c068f94189b 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -673,6 +673,26 @@ export default class TypeScriptServiceClient extends Disposable implements IType return this.toPath(document.uri) || undefined; } + public hasCapabilityForResource(resource: vscode.Uri, capability: ClientCapability): boolean { + switch (capability) { + case ClientCapability.Semantic: + { + switch (resource.scheme) { + case fileSchemes.file: + case fileSchemes.untitled: + return true; + default: + return false; + } + } + case ClientCapability.Syntax: + case ClientCapability.EnhancedSyntax: + { + return true; + } + } + } + public toResource(filepath: string): vscode.Uri { if (filepath.startsWith(this.inMemoryResourcePrefix)) { const resource = vscode.Uri.parse(filepath.slice(1)); diff --git a/extensions/typescript-language-features/src/utils/fileSchemes.ts b/extensions/typescript-language-features/src/utils/fileSchemes.ts index 46b8467879d..d465a60326e 100644 --- a/extensions/typescript-language-features/src/utils/fileSchemes.ts +++ b/extensions/typescript-language-features/src/utils/fileSchemes.ts @@ -6,8 +6,6 @@ export const file = 'file'; export const untitled = 'untitled'; export const git = 'git'; -export const pr = 'pr'; -export const privateScheme = 'private'; /** Live share scheme */ export const vsls = 'vsls'; export const walkThroughSnippet = 'walkThroughSnippet'; @@ -22,7 +20,5 @@ export const semanticSupportedSchemes = [ */ export const disabledSchemes = new Set([ git, - vsls, - privateScheme, - pr, + vsls ]); From a6833ed84119264c5cc05460419d814bc7036b84 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Tue, 8 Sep 2020 16:46:43 -0500 Subject: [PATCH 90/98] proper fix for #105202 (#106293) --- .../src/tsServer/versionManager.ts | 3 +-- .../src/tsServer/versionProvider.electron.ts | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/typescript-language-features/src/tsServer/versionManager.ts b/extensions/typescript-language-features/src/tsServer/versionManager.ts index 069d6d683d4..4811fefd3a7 100644 --- a/extensions/typescript-language-features/src/tsServer/versionManager.ts +++ b/extensions/typescript-language-features/src/tsServer/versionManager.ts @@ -5,7 +5,6 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import * as path from 'path'; import { TypeScriptServiceConfiguration } from '../utils/configuration'; import { Disposable } from '../utils/dispose'; import { ITypeScriptVersionProvider, TypeScriptVersion } from './versionProvider'; @@ -110,7 +109,7 @@ export class TypeScriptVersionManager extends Disposable { run: async () => { await this.workspaceState.update(useWorkspaceTsdkStorageKey, true); const tsConfig = vscode.workspace.getConfiguration('typescript'); - await tsConfig.update('tsdk', path.dirname(version.tsServerPath), false); + await tsConfig.update('tsdk', version.pathLabel, false); this.updateActiveVersion(version); }, }; diff --git a/extensions/typescript-language-features/src/tsServer/versionProvider.electron.ts b/extensions/typescript-language-features/src/tsServer/versionProvider.electron.ts index 15107bc4b5b..760f82d7b09 100644 --- a/extensions/typescript-language-features/src/tsServer/versionProvider.electron.ts +++ b/extensions/typescript-language-features/src/tsServer/versionProvider.electron.ts @@ -104,7 +104,8 @@ export class DiskTypeScriptVersionProvider implements ITypeScriptVersionProvider return [ new TypeScriptVersion(source, serverPath, - DiskTypeScriptVersionProvider.getApiVersion(serverPath)) + DiskTypeScriptVersionProvider.getApiVersion(serverPath), + tsdkPathSetting) ]; } From 1fbd17331e674770475b793b2a6fe3e4855fd321 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Sep 2020 14:53:55 -0700 Subject: [PATCH 91/98] Only enable 'open with' on files Fixes #106291 --- .../workbench/contrib/files/browser/fileActions.contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index 13402773565..26e04e608a9 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -428,7 +428,7 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, { id: OPEN_WITH_EXPLORER_COMMAND_ID, title: nls.localize('explorerOpenWith', "Open With..."), }, - when: ContextKeyExpr.and(ExplorerRootContext.toNegated(), ExplorerResourceAvailableEditorIdsContext), + when: ContextKeyExpr.and(ExplorerFolderContext.toNegated(), ExplorerResourceAvailableEditorIdsContext), }); MenuRegistry.appendMenuItem(MenuId.ExplorerContext, { From 4c7071e9ab3dfbdefada0de7bcdcd6de44c5252a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Sep 2020 15:23:43 -0700 Subject: [PATCH 92/98] Add WebviewView.description Allow configuring the description for webview views. This is rendered next to the title in a less prominently in the title --- src/vs/vscode.proposed.d.ts | 5 +++++ .../api/browser/mainThreadWebviewViews.ts | 18 ++++++++++++++---- .../workbench/api/common/extHost.protocol.ts | 1 + .../workbench/api/common/extHostWebviewView.ts | 14 ++++++++++++++ .../webviewView/browser/webviewViewPane.ts | 14 ++++++++++---- .../webviewView/browser/webviewViewService.ts | 1 + 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index b0b5547fa83..99fd543ff64 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2062,6 +2062,11 @@ declare module 'vscode' { */ title?: string; + /** + * Human-readable string which is rendered less prominently in the title. + */ + description?: string; + /** * Event fired when the view is disposed. * diff --git a/src/vs/workbench/api/browser/mainThreadWebviewViews.ts b/src/vs/workbench/api/browser/mainThreadWebviewViews.ts index 248af0860e6..f906a84854c 100644 --- a/src/vs/workbench/api/browser/mainThreadWebviewViews.ts +++ b/src/vs/workbench/api/browser/mainThreadWebviewViews.ts @@ -29,13 +29,15 @@ export class MainThreadWebviewsViews extends Disposable implements extHostProtoc } public $setWebviewViewTitle(handle: extHostProtocol.WebviewHandle, value: string | undefined): void { - const webviewView = this._webviewViews.get(handle); - if (!webviewView) { - throw new Error('unknown webview view'); - } + const webviewView = this.getWebviewView(handle); webviewView.title = value; } + public $setWebviewViewDescription(handle: extHostProtocol.WebviewHandle, value: string | undefined): void { + const webviewView = this.getWebviewView(handle); + webviewView.description = value; + } + public $registerWebviewViewProvider(viewType: string, options?: { retainContextWhenHidden?: boolean }): void { if (this._webviewViewProviders.has(viewType)) { throw new Error(`View provider for ${viewType} already registered`); @@ -89,5 +91,13 @@ export class MainThreadWebviewsViews extends Disposable implements extHostProtoc provider.dispose(); this._webviewViewProviders.delete(viewType); } + + private getWebviewView(handle: string): WebviewView { + const webviewView = this._webviewViews.get(handle); + if (!webviewView) { + throw new Error('unknown webview view'); + } + return webviewView; + } } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 49f22175d18..8621b58cd6d 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -640,6 +640,7 @@ export interface MainThreadWebviewViewsShape extends IDisposable { $unregisterWebviewViewProvider(viewType: string): void; $setWebviewViewTitle(handle: WebviewHandle, value: string | undefined): void; + $setWebviewViewDescription(handle: WebviewHandle, value: string | undefined): void; } export interface WebviewPanelViewStateData { diff --git a/src/vs/workbench/api/common/extHostWebviewView.ts b/src/vs/workbench/api/common/extHostWebviewView.ts index cc23d2a1fcd..40758443c25 100644 --- a/src/vs/workbench/api/common/extHostWebviewView.ts +++ b/src/vs/workbench/api/common/extHostWebviewView.ts @@ -23,6 +23,7 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView { #isDisposed = false; #isVisible: boolean; #title: string | undefined; + #description: string | undefined; constructor( handle: extHostProtocol.WebviewHandle, @@ -70,6 +71,19 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView { } } + public get description(): string | undefined { + this.assertNotDisposed(); + return this.#description; + } + + public set description(value: string | undefined) { + this.assertNotDisposed(); + if (this.#description !== value) { + this.#description = value; + this.#proxy.$setWebviewViewDescription(this.#handle, value); + } + } + public get visible(): boolean { return this.#isVisible; } public get webview(): vscode.Webview { return this.#webview; } diff --git a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts index 31ce142a161..4ca95f26344 100644 --- a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts +++ b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts @@ -23,7 +23,7 @@ import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewl import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IWebviewService, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; -import { IWebviewViewService } from 'vs/workbench/contrib/webviewView/browser/webviewViewService'; +import { IWebviewViewService, WebviewView } from 'vs/workbench/contrib/webviewView/browser/webviewViewService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; declare const ResizeObserver: any; @@ -158,13 +158,19 @@ export class WebviewViewPane extends ViewPane { await this.extensionService.activateByEvent(`onView:${this.id}`); let self = this; - await this.webviewViewService.resolve(this.id, { + const webviewView: WebviewView = { webview, onDidChangeVisibility: this.onDidChangeBodyVisibility, onDispose: this.onDispose, + get title() { return self.title; }, - set title(value: string) { self.updateTitle(value); } - }, source.token); + set title(value: string) { self.updateTitle(value); }, + + get description(): string | undefined { return self.titleDescription; }, + set description(value: string | undefined) { self.updateTitleDescription(value); }, + }; + + await this.webviewViewService.resolve(this.id, webviewView, source.token); }); } } diff --git a/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts b/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts index 5de370ac42d..f29936baa8f 100644 --- a/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts +++ b/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts @@ -13,6 +13,7 @@ export const IWebviewViewService = createDecorator('webview export interface WebviewView { title?: string; + description?: string; readonly webview: WebviewOverlay; From 17dcafe6c692ed37477d328b5ffb9c4f8f7b0bbd Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Sep 2020 15:35:49 -0700 Subject: [PATCH 93/98] Remove manual strikethroughs for deprecated properties in vscode.d.ts Now that TS has support for `@deprecated`, these manual strike throughs should no longer be required. --- src/vs/vscode.d.ts | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index d3835e3aabe..680d2921f0f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1160,7 +1160,7 @@ declare module 'vscode' { revealRange(range: Range, revealType?: TextEditorRevealType): void; /** - * ~~Show the text editor.~~ + * Show the text editor. * * @deprecated Use [window.showTextDocument](#window.showTextDocument) instead. * @@ -1170,7 +1170,7 @@ declare module 'vscode' { show(column?: ViewColumn): void; /** - * ~~Hide the text editor.~~ + * Hide the text editor. * * @deprecated Use the command `workbench.action.closeActiveEditor` instead. * This method shows unexpected behavior and will be removed in the next major update. @@ -2498,9 +2498,9 @@ declare module 'vscode' { } /** - * ~~MarkedString can be used to render human-readable text. It is either a markdown string + * MarkedString can be used to render human-readable text. It is either a markdown string * or a code-block that provides a language and a code snippet. Note that - * markdown strings will be sanitized - that means html will be escaped.~~ + * markdown strings will be sanitized - that means html will be escaped. * * @deprecated This type is deprecated, please use [`MarkdownString`](#MarkdownString) instead. */ @@ -2753,7 +2753,7 @@ declare module 'vscode' { constructor(name: string, kind: SymbolKind, containerName: string, location: Location); /** - * ~~Creates a new symbol information object.~~ + * Creates a new symbol information object. * * @deprecated Please use the constructor taking a [location](#Location) object. * @@ -3874,12 +3874,12 @@ declare module 'vscode' { /** * @deprecated Use `CompletionItem.insertText` and `CompletionItem.range` instead. * - * ~~An [edit](#TextEdit) which is applied to a document when selecting + * An [edit](#TextEdit) which is applied to a document when selecting * this completion. When an edit is provided the value of - * [insertText](#CompletionItem.insertText) is ignored.~~ + * [insertText](#CompletionItem.insertText) is ignored. * - * ~~The [range](#Range) of the edit must be single-line and on the same - * line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~ + * The [range](#Range) of the edit must be single-line and on the same + * line completions were [requested](#CompletionItemProvider.provideCompletionItems) at. */ textEdit?: TextEdit; @@ -5220,7 +5220,7 @@ declare module 'vscode' { show(preserveFocus?: boolean): void; /** - * ~~Reveal this channel in the UI.~~ + * Reveal this channel in the UI. * * @deprecated Use the overload with just one parameter (`show(preserveFocus?: boolean): void`). * @@ -6179,7 +6179,7 @@ declare module 'vscode' { constructor(taskDefinition: TaskDefinition, scope: WorkspaceFolder | TaskScope.Global | TaskScope.Workspace, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomExecution, problemMatchers?: string | string[]); /** - * ~~Creates a new task.~~ + * Creates a new task. * * @deprecated Use the new constructors that allow specifying a scope for the task. * @@ -8134,8 +8134,8 @@ declare module 'vscode' { export function setStatusBarMessage(text: string): Disposable; /** - * ~~Show progress in the Source Control viewlet while running the given callback and while - * its returned promise isn't resolve or rejected.~~ + * Show progress in the Source Control viewlet while running the given callback and while + * its returned promise isn't resolve or rejected. * * @deprecated Use `withProgress` instead. * @@ -9571,8 +9571,8 @@ declare module 'vscode' { export const fs: FileSystem; /** - * ~~The folder that is open in the editor. `undefined` when no folder - * has been opened.~~ + * The folder that is open in the editor. `undefined` when no folder + * has been opened. * * @deprecated Use [`workspaceFolders`](#workspace.workspaceFolders) instead. */ @@ -9952,7 +9952,7 @@ declare module 'vscode' { export const onDidChangeConfiguration: Event; /** - * ~~Register a task provider.~~ + * Register a task provider. * * @deprecated Use the corresponding function on the `tasks` namespace instead * @@ -10691,8 +10691,8 @@ declare module 'vscode' { export namespace scm { /** - * ~~The [input box](#SourceControlInputBox) for the last source control - * created by the extension.~~ + * The [input box](#SourceControlInputBox) for the last source control + * created by the extension. * * @deprecated Use SourceControl.inputBox instead */ From f79540dc651e2bd6ac7399a4c90bec1ab78e8849 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Sep 2020 17:19:03 -0700 Subject: [PATCH 94/98] Add show method to webview view Fixes #106085 --- src/vs/vscode.proposed.d.ts | 9 +++++++++ src/vs/workbench/api/browser/mainThreadWebviewViews.ts | 5 +++++ src/vs/workbench/api/common/extHost.protocol.ts | 2 ++ src/vs/workbench/api/common/extHostWebviewView.ts | 5 +++++ .../contrib/webviewView/browser/webviewViewPane.ts | 7 ++++++- .../contrib/webviewView/browser/webviewViewService.ts | 2 ++ 6 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 99fd543ff64..b732e88f1ec 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -2095,6 +2095,15 @@ declare module 'vscode' { * Note that hiding a view using the context menu instead disposes of the view and fires `onDidDispose`. */ readonly onDidChangeVisibility: Event; + + /** + * Reveal the view in the UI. + * + * If the view is collapsed, this will expand it. + * + * @param preserveFocus When `true` the view will not take focus. + */ + show(preserveFocus?: boolean): void; } interface WebviewViewResolveContext { diff --git a/src/vs/workbench/api/browser/mainThreadWebviewViews.ts b/src/vs/workbench/api/browser/mainThreadWebviewViews.ts index f906a84854c..eae46c714d0 100644 --- a/src/vs/workbench/api/browser/mainThreadWebviewViews.ts +++ b/src/vs/workbench/api/browser/mainThreadWebviewViews.ts @@ -38,6 +38,11 @@ export class MainThreadWebviewsViews extends Disposable implements extHostProtoc webviewView.description = value; } + public $show(handle: extHostProtocol.WebviewHandle, preserveFocus: boolean): void { + const webviewView = this.getWebviewView(handle); + webviewView.show(preserveFocus); + } + public $registerWebviewViewProvider(viewType: string, options?: { retainContextWhenHidden?: boolean }): void { if (this._webviewViewProviders.has(viewType)) { throw new Error(`View provider for ${viewType} already registered`); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 2f9b6700921..da717e7f0e1 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -641,6 +641,8 @@ export interface MainThreadWebviewViewsShape extends IDisposable { $setWebviewViewTitle(handle: WebviewHandle, value: string | undefined): void; $setWebviewViewDescription(handle: WebviewHandle, value: string | undefined): void; + + $show(handle: WebviewHandle, preserveFocus: boolean): void; } export interface WebviewPanelViewStateData { diff --git a/src/vs/workbench/api/common/extHostWebviewView.ts b/src/vs/workbench/api/common/extHostWebviewView.ts index 40758443c25..dcb76f3afd3 100644 --- a/src/vs/workbench/api/common/extHostWebviewView.ts +++ b/src/vs/workbench/api/common/extHostWebviewView.ts @@ -99,6 +99,11 @@ class ExtHostWebviewView extends Disposable implements vscode.WebviewView { this.#onDidChangeVisibility.fire(); } + public show(preserveFocus?: boolean): void { + this.assertNotDisposed(); + this.#proxy.$show(this.#handle, !!preserveFocus); + } + private assertNotDisposed() { if (this.#isDisposed) { throw new Error('Webview is disposed'); diff --git a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts index 4ca95f26344..ad5ba7e2796 100644 --- a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts +++ b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts @@ -21,7 +21,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; -import { IViewDescriptorService } from 'vs/workbench/common/views'; +import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views'; import { IWebviewService, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { IWebviewViewService, WebviewView } from 'vs/workbench/contrib/webviewView/browser/webviewViewService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -57,6 +57,7 @@ export class WebviewViewPane extends ViewPane { @IProgressService private readonly progressService: IProgressService, @IWebviewService private readonly webviewService: IWebviewService, @IWebviewViewService private readonly webviewViewService: IWebviewViewService, + @IViewsService private readonly viewService: IViewsService, ) { super({ ...options, titleMenuId: MenuId.ViewTitle }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService); @@ -168,6 +169,10 @@ export class WebviewViewPane extends ViewPane { get description(): string | undefined { return self.titleDescription; }, set description(value: string | undefined) { self.updateTitleDescription(value); }, + + show: (preserveFocus) => { + this.viewService.openView(this.id, !preserveFocus); + } }; await this.webviewViewService.resolve(this.id, webviewView, source.token); diff --git a/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts b/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts index f29936baa8f..60d4a3a7a6f 100644 --- a/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts +++ b/src/vs/workbench/contrib/webviewView/browser/webviewViewService.ts @@ -19,6 +19,8 @@ export interface WebviewView { readonly onDidChangeVisibility: Event; readonly onDispose: Event; + + show(preserveFocus: boolean): void; } export interface IWebviewViewResolver { From 940bfbd6a6294ca981f88c1f20a6613eb2090dc8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 8 Sep 2020 17:41:55 -0700 Subject: [PATCH 95/98] Skip failing test --- .../userData/test/electron-browser/fileUserDataProvider.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts index f7ed39ac45d..f04095592fe 100644 --- a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts +++ b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts @@ -59,7 +59,7 @@ suite('FileUserDataProvider', () => { disposables.clear(); }); - test('exists return false when file does not exist', async () => { + test.skip('exists return false when file does not exist', async () => { const exists = await testObject.exists(environmentService.settingsResource); assert.equal(exists, false); }); From 98ab62b6b6dc16e7cd07295505f16c992ca13e64 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 9 Sep 2020 08:03:52 +0200 Subject: [PATCH 96/98] fix #106283 --- .../test/electron-browser/fileUserDataProvider.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts index f04095592fe..f904fe3fb8d 100644 --- a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts +++ b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts @@ -7,6 +7,7 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as uuid from 'vs/base/common/uuid'; +import * as pfs from 'vs/base/node/pfs'; import { IFileService, FileChangeType, IFileChange, IFileSystemProviderWithFileReadWriteCapability, IStat, FileType, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; @@ -55,8 +56,8 @@ suite('FileUserDataProvider', () => { }); teardown(async () => { - await testObject.del(rootResource, { recursive: true }); disposables.clear(); + await pfs.rimraf(rootResource.fsPath, pfs.RimRafMode.MOVE); }); test.skip('exists return false when file does not exist', async () => { From bb27a30efa01771b217b3844171b36fcf961bc2b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 9 Sep 2020 08:06:13 +0200 Subject: [PATCH 97/98] enable test --- .../userData/test/electron-browser/fileUserDataProvider.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts index f904fe3fb8d..87bcb8ef598 100644 --- a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts +++ b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts @@ -60,7 +60,7 @@ suite('FileUserDataProvider', () => { await pfs.rimraf(rootResource.fsPath, pfs.RimRafMode.MOVE); }); - test.skip('exists return false when file does not exist', async () => { + test('exists return false when file does not exist', async () => { const exists = await testObject.exists(environmentService.settingsResource); assert.equal(exists, false); }); From 1d177e247c5dc16f772d0b78aaa6cbbe5944124b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 9 Sep 2020 08:27:49 +0200 Subject: [PATCH 98/98] fix #106283 --- .../electron-browser/fileUserDataProvider.test.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts index 87bcb8ef598..999fade0edd 100644 --- a/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts +++ b/src/vs/workbench/services/userData/test/electron-browser/fileUserDataProvider.test.ts @@ -7,7 +7,6 @@ import * as assert from 'assert'; import * as os from 'os'; import * as path from 'vs/base/common/path'; import * as uuid from 'vs/base/common/uuid'; -import * as pfs from 'vs/base/node/pfs'; import { IFileService, FileChangeType, IFileChange, IFileSystemProviderWithFileReadWriteCapability, IStat, FileType, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { FileService } from 'vs/platform/files/common/fileService'; import { NullLogService } from 'vs/platform/log/common/log'; @@ -31,6 +30,7 @@ suite('FileUserDataProvider', () => { let backupWorkspaceHomeOnDisk: URI; let environmentService: IWorkbenchEnvironmentService; const disposables = new DisposableStore(); + let fileUserDataProvider: FileUserDataProvider; setup(async () => { const logService = new NullLogService(); @@ -50,14 +50,15 @@ suite('FileUserDataProvider', () => { backupWorkspaceHomeOnDisk = joinPath(backupHome, workspaceId); await Promise.all([testObject.createFolder(userDataHomeOnDisk), testObject.createFolder(backupWorkspaceHomeOnDisk)]); - const userDataFileSystemProvider = new FileUserDataProvider(userDataHomeOnDisk, backupWorkspaceHomeOnDisk, diskFileSystemProvider, environmentService, logService); - disposables.add(userDataFileSystemProvider); - disposables.add(testObject.registerProvider(Schemas.userData, userDataFileSystemProvider)); + fileUserDataProvider = new FileUserDataProvider(userDataHomeOnDisk, backupWorkspaceHomeOnDisk, diskFileSystemProvider, environmentService, logService); + disposables.add(fileUserDataProvider); + disposables.add(testObject.registerProvider(Schemas.userData, fileUserDataProvider)); }); teardown(async () => { + fileUserDataProvider.dispose(); // need to dispose first, otherwise del will fail (https://github.com/microsoft/vscode/issues/106283) + await testObject.del(rootResource, { recursive: true }); disposables.clear(); - await pfs.rimraf(rootResource.fsPath, pfs.RimRafMode.MOVE); }); test('exists return false when file does not exist', async () => {