mirror of
https://github.com/coder/code-server.git
synced 2026-05-24 13:17:28 +02:00
Squashed 'lib/vscode/' changes from fd6f3bce670..ead2c2ab0f5
ead2c2ab0f5 Merge pull request #120858 from microsoft/alex/1-55-2 bfb2654224e Pick up new distro version and bump version 08a217c4d27 Merge pull request #120733 from microsoft/joao/release/1.55/fix-build 6b89f1aaa2e Don't call node-gyp anymore (#120673) 6e3220a31a9 Merge shellEnv into process.env (#120332) 5dee7d559ff Update to vscode-proxy-agent 0.8.2 (#120354) 91fa7f030d2 Merge pull request #120519 from microsoft/misolori/icon-updates c5e030273bf Merge branch 'release/1.55' into misolori/icon-updates 8be12407ad0 bump version to 1.55.1 (#120379) d6e72b493ce debug: update js-debug (#120358) b7d152d5b2f Update distro c185983a683 Fix table list height. Fixes #120062 (#120102) (#120168) c71be15869a fix powershell profile source (#120138) 4c2a1fa6306 handle error when wsl is not installed (#120128) e3297826776 Merge pull request #120107 from microsoft/aeschli/120103 c7f963cb27d Moves extension prop out of proposed 55f4c2ec1e2 update typescript-vscode-sh-plugin 26a60dbecac Merge pull request #120081 from microsoft/sandy081/fix119975 5753889f2d1 remove overflow action when there are no overflows be363080a36 fixes #120066 (#120080) 554774c21d6 Merge pull request #119983 from microsoft/lramos15/notebookViewType 428daa3650c Merge pull request #119990 from microsoft/tyriar/r155_wsl_compile 64876cb88e2 Fix test compilation 00296950306 [Getting Started] new file => new untitled file rather than explorer's new file (#119981) 2a8113f7231 Enable terminal event batching from ptyHost (#117268) aefdd723bd0 Merge pull request #119987 from microsoft/tyriar/r155_wsl_setting 98aeda8479a Remove RemoteHub from desktop stable (#119972) 981a2b53abc Merge pull request #119977 from microsoft/digitarald/fix-115327 a3514cd1481 allow terminal profiles w a source to have args (#119967) 78636f2c133 Fixes #115327 with HC images for GS setup/beginners. b72964aaace iPad OS ctrl + c in terminal (#119979) a84f17acbbf displayDetectedWslProfiles -> useWslProfiles 1b0b1c67f35 Merge pull request #119973 from microsoft/digitarald-ces-distro-update c97d55a2131 debug: fix stop on entry not working after launch.json change (#119980) c7068ae9331 Respect viewtype for reopen with in notebooks 59b2869bdb1 Distro update 7208128b818 Merge pull request #119377 from microsoft/digitarald/ces 522cb113395 Ignore extension that is being installed d06d2f1d624 Update distro 80c9c2bfdd8 Adopt writeSync maxSubsequentCalls dd8ce595220 xterm@4.12.0-beta.7 1eb987f85f1 LocalizationService.update no longer needed. Fixes https://github.com/microsoft/vssaas-planning/issues/3290 70aab480c5a update labels for break commands 49ad7ad4f53 fix optional service typing a0aea2c02ab Fix counting executing cells incorrectly Fix #119921 961935482ff Fix build 33c5dbf0407 Force internal execution metadata to be transient Fix #119853 0865813de51 showQuickLaunchWslProfiles -> displayDetectedWslProfiles 91b6bcd2cce Fix spelling error 5bf977258c5 Slide to first category for new users 72bb797593f Don't scroll to first category if already have Fix #119842 Fix #119339 0a7dde45706 Update distro 9be5cb7f482 Fixes #118772: Remove a disconnected remote extension host from `extensionHostManagers` c9829c32d11 Surface pwsh as a profile on mac/linux if it's installed b59b0c5051e update distro 647f8724320 Roll back to `vscode-textmate@5.2.0` a564f58b13f Fixes #119065: Also listen for EPIPE errors on the socket 99c8eb69942 Fixes regex - codespaces remotes are missing .git ab39731a1e6 Avoid rolling back `vscode-textmate` 9b564ad40db update distro 85d03e9c382 Fixes #119915: Go back to `vscode-oniguruma@1.3.1` f4f1bdb9265 update distro e15a185f6ee Merge branch 'main' into notebook/dev a6cef60b50f notebook toolbar init display be none. fix #119910. 654b5e80469 update to latest `vscode-oniguruma` 5a92084faeb Use ThrottledDelayer per review feedback. 357c13ac467 localize info message 5dcccb92e38 fix #119854 1ca4e703ba8 Optimizing newly add getting started images. 71d2102d7d0 fix #119803 c5d901812cd Merge pull request #119883 from microsoft/tyriar/webgl_fix f7cc0f2c79d Adding light and hc getting started images. Closes #115325 and #115327 64256f22d66 Merge pull request #119895 from gregvanl/settingTypos ad659fb25aa Allow null in profiles config 3e6f65a3acd Merge branch 'main' of https://github.com/microsoft/vscode into main a30b6bfdc3b remove default value for overrideName 19bbe2edbee Remove extra space from error message 7ac7d4438a9 fix #119672 975115a2cb4 Setting descriptions typos and formatting fe6b3e258b6 Re-enable measuring c5a8eed0334 Accept array or single item for output items methods #119601 996391b87d3 Move proposed api piece into stable typings 6ebe2a14f37 fix #119852. 3d1d01690df Fix canvas -> dom fallback da992a171e2 fix scroll cells from bottom view. 9ab0fb227ee use app scope 81a08478ef1 updated notebooks ff869cd3581 Merge pull request #119878 from microsoft/isidorn/notificationVisible 1a184f9e9dc add visible flag to notification b70c4fee0d8 Fix default webgl renderer ad026f8130c ces: use ThrottledDelayer 755cbf5412a Merge branch 'main' into notebook/dev 08c4cd87e3c Reenable localization tests. 5064fae294b Fix #118134 e8111f76b5b Fix #119855 5b636c4a7b2 Revert "Fixes #111814 (#119475)" 6f726bcdf6a fix #118442 557c4b56995 update verification members 63f1721ed85 don't store output in GH issue notebooks 05ce54df77c testing: remove unused contributions ce9298464e4 bring notebook actions back to editor title bar menu static. ceff50539f0 re #119706. ef80780f632 fix #118996. 383fb64cc58 remove displayOrder and fix #119830 81ba1dae860 Fix #117540 1a425eacb83 Accept single outputs or arrays in execution task output edit methods Fix #119601 75ed057885c fix #117937 1e6697ed77d fix #119561. f0eacf87700 fix #119767. 1d3cbad0102 Wait for extension registration when resolving notebook viewType Fix #119686 ab317a2280e Hide select terminal profile in yarn web a0e8b01ec49 testing: polish wording of testing.autoRun.mode 189fb15df90 Check PATH when validating non-absolute paths 5c6836eb44d Fix #119699 b63cfb3a8b6 skip test and remove unused code 8d6c2a23888 Make drop shadow much more subtle Closes #119633 23713de2bee don't emit events when splices are empty, fixes https://github.com/microsoft/vscode/issues/119608 5a241c767a9 fix https://github.com/microsoft/vscode/issues/119363 22212f5de84 use APIs over commands, fixes (?) https://github.com/microsoft/vscode/issues/119437 bd2402a6e8e Add double-click to collapse Fix #113248 c45540033a5 Aadd messge when getting started empty closes #119496 d115bb2a977 clean up statProvider, use existsFile, fix #119807 008e91bd7c9 contribute editor toolbar actions by checking active editor other than focus/blur. fix #119706 38160c823c8 Fixes codespaces fork on push d765f3a43c7 testing: fix list view not working 0fb1882984e fix: items from results being added to collections and breaking decorations ab94ad2b8f5 clean-up validateProfilePaths 46d5d38dd28 fix #119672 ebec68bc3d9 fix #119728. 2616ee94f38 fix #119775. 6384c7462f8 fix #119677 abaa23cdf39 fix #119774 09f43fd6aa4 testing: fix exclusion filter in view e4bb4c1b77f testing: fix results disappearing or not showing for new files cd31f2cdfac testing: fix test appearing on first line, remove location from TestItems 60849897630 fix #119773. 15ba6b4c957 Revert "extract _assertWebviewForMarkdownPreview" 2c232fed6af Update README.md e3e7fb0b2ab Set explicit mode for markdown preview code addf2d6d9e9 Fix spelling for gitignore f8c1ffbb0cf Build simple-browser media during watch 68e582380d7 Maybe fix bug where sync task doesn't get checked d087b5cf4f1 Add back old getting started flow as "walkthroughs" e5afd670959 extract _assertWebviewForMarkdownPreview d13e68e6cf5 avoid markdown preview removal when it is disabled. 8a960081e55 fix #119771. f1334e055c8 Polish select default profile quick pick 563a617ca2a Applied review feedback and tweaked heuristics 8aac8643d77 Use 'terminal profile' instead of quick launch profile, change icon 64b4f5b934d use final DAP 1.46.0 f04acbd22a4 node-debug@1.44.19 0db170025e4 Fix terminal dropdown rebuilding itself 8ceb8b96153 Rename "expand cell content" to "input" Fix #119762 9e2e6cded21 Change cell pending indicator to clock codicon Fix #119739 ddb7709cbf3 Fix #119700 fix #119731 fix #119701 Co-authored-by: Daniel Imms <daimms@microsoft.com> 51c403193b6 do no change selections if the action is from toolbar. 7d19db7ad9b fix #119769. f934e058c75 Fix profile permissions prompt on linux/mac 6dbb3800c5a Fix #116424 b8f5fd7f1b6 debug: update js-debug c88146514ca debug: bump node-debug 8387a46298e snap-build-linux.yml: use "snap pack" to get LZO (#119478) 792c2318898 fixes #118660 eb135ec46e8 Fix #119626 e353502fb9d fixes #118045 f9d92f0fc6c Fix #119723 948839aa445 Fix #119660 6aa6260a843 fixes #118852 da1ed96b6a8 fix code-cli.bat aeedd850ac4 fix #119073 2d9069014eb Add a placeholder for already forwarded root ports (#119792) 74cf3fb2021 Fixes #119529: Wait for eager extensions to activate before launching extension tests 5fbba30c046 Better Fix #119573 9a646e1967c fixes #119487 f91c464f1e1 Merge pull request #119784 from microsoft/tyriar/profile_schema 9f37f3f04ee Pull common unix/win parts into shared function ac74acadddf Only set when win profile is non-null f4fbc4abd78 Merge remote-tracking branch 'origin/main' into tyriar/profile_schema a83eb44ecd5 fixes #119488 301e9ac1db8 fixes #119580 a34297a6085 fix #119384 47f0413ea29 window indicator: based on workspace config file location. For #119752 40d104ad84a Add schema to profiles settings 771b0192f43 window listeners handling 27fc3b41ed4 scm: add trace logs for #113803 08d5310eb18 update verifications notebook 8933c1564d0 Don't create a terminal on panel show without proc support c55aff63798 API feedback (WorkspaceTrustRequest -> WorkspaceTrustRequestOptions) (#119658) 3eb6fec8cd6 Be more specific when listening for marker events 4ad88afc1f2 Fix #119573 42b8129c64e don't emit events when splices are empty, fixes https://github.com/microsoft/vscode/issues/119608 4dedb019f85 Clear data written flag on manual relaunch 1c3990938b8 Fix #119572 443b6f71bf8 fix https://github.com/microsoft/vscode/issues/119363 c6a8cb7f091 Fix #119698 8437d38d364 Fix #119753 a1ecc83a5d3 Merge branch 'main' into notebook/dev a233c8683a2 workspaces history - proper check for untitled 7a1302a2b6c remote indicator - fix npe 90484dda2b2 shared process - also log if window visible 5245290dc56 file working copy - update test to account for events 2b66dfe0218 skip flaky tests. d5abce78ab7 Remove unsued var ff42bf46511 Disable markdown renders by default 279b4d92317 fix #119724. 514eefb789e Don't send execute request for markdown cells Fix #119734 91939fb9e7d handle invalid ignore options and avoid early dispose. fix #119638 548de3ac8ba fix #119708 85770c31911 hide all outputs (builtin and renderers) fix #119690. a8b8e7bd483 Fixes #118979: Reduce find widget's z-index 11c0904a568 Don't enable the new markdown renderer if accessibility mode is enabled 376b25645be Only show selection if there multiple cells selected 31987b11c6f Merge pull request #117758 from conwnet/main 02b394a1a5c Add a special editor option to control the readonly textarea attribute a9aebe3bce0 Merge remote-tracking branch 'origin/main' into pr/conwnet/117758 07eb4d9e076 Fix #114965 d7e1da38b17 Fix Linux referring to osx 8d3d8e0cd04 html: add vscode-languageserver-textdocument as dependency bd18fe9bcec Fixes #119632: Handle `undefined` when validating a range 8c7a3d8f6ca html: fix compile errors c099b873de7 update distro 0f65e64c2a3 Fixes #119636 - 🤦 76c5d1707cb RunOneScheduler and code cleanup for CES b3058d60df4 update distro 7b7e3d9e1e5 Fixes #118041: Add workaround for `UTF16` `TextDecoder` eating up `0xFEFF` and `0xFFFE` c7ad1b9020d Add sequences to type ahead comment 97b2514ca71 include source.id for progress notifications 6349f37d80f Merge pull request #119373 from wdesgardin/fix/replace-pattern-preserve-case cca8a48b17a Restore notebook smoketests, Fix #113882 3225cf3037a update distro 3b44bb422d3 Only set detected profile if value is non-null 75f796dfb48 notificationTelemetry: id should always be a string 4eb625f0cf0 [html] update service a53ce8af3b5 update remote indicator on workspace change 11e79c76d89 Merge pull request #119607 from NotWearingPants/patch-3 a780b76b9d5 Keep text from jumping when showing port input Fixes microsoft/vscode-remote-release#4729 61eb66d6c4b Fixed recent typo from afca445 64381abea97 unconfiguredPortsAttributes -> otherPortsAttributes Fixes microsoft/vscode-remote-release#4732 73b9e6679d5 Update README.md a535549d893 update distro f600cd9ef21 Fix compilation errors: update to latest `vscode-textmate` 684a4526059 Improve resolveTask documentation ab12e39334e update distro 788c9dfdc48 update deps afca44535df Add a trace statement to be able to track down which implementation handles a `MultiCommand` 9089e0cbd9f Update endgame notebooks b28d8ca9fe0 use APIs over commands, fixes (?) https://github.com/microsoft/vscode/issues/119437 2bc5e538923 Merge branch 'main' into notebook/dev ebe56205433 fix(search): preserve case when match start with lowercase char a6f6b4aa8e3 Add feature flags to control availablity of getting started extension contributions 735e998fca0 update distro 10a74ff5c51 Open to getting started page on extension install 194c37b4cf2 Fix test for latestExecutionSummary init 9fa49ba9415 ignore optional dependencies when webpacking 7a8b665f25a Fix missing prop on cell data 808266d4dec Allow tests to be loaded asynchronously (#119537) 6e2cb85e207 debug: update js-debug fdc4f23b108 Add double-click to collapse Fix #113248 35ae55affde diff editor output decorations fix. aac461a3124 Improves behavior for #114945 851a849d2ce Don't validate non-absolute paths 2cde743fe21 Pass event modifier data when clicking on markdown cell 4cb75127664 add quick launch profiles for unix 9c00242866c updating telemetry module for built-in exts 3d987fdc5b3 fixes #117782 084fd5171a1 Terminal profile fixes (#119352) 7483058a0ab update distro 1f5dd686c8f Disable select for notebook preview cells in webviews a685b5976ba Exclude DSR from type ahead 4b3ba3ea44c Removes proposed api check 44ffe526ffe auto layout for editors in output container, fix #119048. d4a0fa9ca6d Build getting started service at startup in order to init event listeners d657779c014 Improve getting started response to slow network conditions for content overrides efb75d7262e Move override delay to conver all exp service usage 018eca5246f fix #118615 'scm/resourceXXX/context' extension point descriptions were muddled 0179466adac Move getting started service to workbench/contrib Closes #118603 e8290f52f4f run oss tool for 1.55 db670f1002c Use shellEnv (#108804) 64042213ed2 Bumps RemoteHub to 0.1.2 f201f7bc68a Fix notebook test 08cf8038dfd Merge pull request #95882 from jeanp413/fix-95671 4977db85c01 update tas-client-umd 7e719d3f046 Merge branch 'notebook/dev' into main 03e1ce6524d Fix getting started items appearing out of order 4a83a80aa7b update diff output height properly (using closure) on resize. 2949009de61 move more logic into abstractRenderer. 55e56ef9153 add options for controlling outputs/metadata in the diff editor. 0089ba3ae1d Bump vscode-emmet-helper, fixes #112675 c95389a7b2d Fix emmet completions in scss (#118666) 7b96cc4c8ba Implement Execution API (#116416) 4b0118871f0 Adds codespaces lookup via command for desktop d46eca3d2dd Merge pull request #119385 from microsoft/merogge/fix 7176a40fc74 Add notebook.inactiveSelectedCellBorder (refs #114156) 64a8be3fa24 fix #117691 a2044cbd78d tweak d909932d240 Fix #118104 33c11ec866f Bumps RemoteHub to 0.1.1 26cdfad1cd0 Fixes #118521 e79b88daadb handle view in terminalView 66961037cc3 Fixes #111814 (#119475) 57aada6cca9 Fix test 5efebbd4c4c Fixes #118270: Add new option to control deleting character pairs and delete by default only auto-inserted closing characters 91e41167e52 file working copy - clarify onDidChangeContent 8cfc30d5741 Fixes #118461: Don't show Open Workspace in the diff editor c148f9a70bf Show error when port is already forwarded Fixes #117571 d239450d9b1 Ensure relaunched processes get shutdown 76b1ad1d1dc Improve profile order, remove profileName from config 6bac57decf7 file working copy - better document resolve() method 0ddc091edc6 some code 💄 a02448d6852 Ensure config service is optional in external terminal 917edde164f Fixes #117534: Allow to mark command args as optional 2cd8246a94b Fixes #118062 4c29fa41c6d Fixes #119416: Use control pictures for NULL and DEL when renderControlCharacters is on cc8748a2397 notificationsTelemetry: change id to be string bbe333f8782 Add tsec exemptions 42c9e63a7ed file working copy - resolve returns void d9d0879741f file working copy - add save as support and a lot of tests 469e4f6e275 chore: bump distro 67eebf8ac58 avoid duplication. 0ab3c62ca2a fix action context detection. 5a0fe1f6a89 remove todo tag d6a0bf700cd Merge branch 'main' into notebook/dev 5a66c91c029 Fixes #117935 a3415e669a8 Fixes #119383: Use `fetch` instead of `importScripts` to avoid deadlock in Safari 4a10c93b2d6 Remove unused argument 307ed64376a Adds RemoteHub as built-in 8290994dbbe Fix localization strings and typo 4995ce93673 More tweaks to geting started category 13ec92fe360 Update getting started category styling e380c34cac7 Fix typos a1c114aa9e6 replace more pathOrPaths with path 1aa0c31b55b pathOrPaths -> path e7aedd975c8 Adjust notebook cell multi-select colors 4bcf96223a7 Fix some getting started crashes 0d83680d528 More CES heuristics work d222e20941c Merge pull request #119328 from microsoft/tyriar/wsl_encoding e92a80bb641 Merge remote-tracking branch 'origin/main' into tyriar/wsl_encoding ee4b50aaa43 Allow creation of quick launch profiles via select default shell command 194f43025f6 Remove log da7c7d1efea Merge branch 'main' into digitarald/ces 4b5354c5f98 alternative version for notebook document. ff3c423cf3f alternative version for notebook document. 6480a6f20ea feat: add option to control scm font size (#115494) d60cac30195 Fix a typo f8acb0d6f63 Adding the 'delete branch...' function to the source control > branch section 6c0c77926ff Improve GitHub repository search 64ebc978e76 Revert "Use rmdirSync instead of rimraf" 0eff78fc42e Merge branch 'notebook/dev' into main 7f9ea9411c8 Reduce default tas override delay to 0 5c0c637a043 Make sure we ignore compiled media files f5146529508 Automatically relaunch terminals when pty host is restarted 7727e93b22e Rename experiment override settings Log when experiments have been overridden for purposes of excluding data from scorecards 07879df53d9 update the layout since editor toolbar height changes 13ceef289f0 experiment service for nb toolbar position 1cd067471e8 Trims url to avoid issues 022d823577a Fixes #110904 - adjusts error regex c2b6d30e9ef Fix input placeholders from 2275dba01afe2b8814d4ebdd67d1027fa51bdcb4 b1770e6ad8a Prompt within 1-8hrs heuristics df3953996da notifications: send telemetry for silent notificatinos, smarter spot for hide event f7f2f08eec5 Update distro 1b7470b25db Try to find ports with a root process (#119341) 421d67ec41a notifications: add source to notification:hide and also send events for silent notificatinos 2275dba01af Change files to include/exclude placeholder to tooltip 3d87801cb0c Merge pull request #119091 from microsoft/joh/nbSerialize 9734ab15dd6 💄 88e87f02bd6 file working copy - make resolve not return "this" b74bae8ced6 refine NotebookCellData converter d6c74de1f5c Merge branch 'main' into notebook/dev 61b73024053 Merge branch 'main' into joh/nbSerialize 3a6c54fb14e no more file watching in notebook diff editor, remove lastResolvedFileStat from notebook editor model 39ea9cac052 Make UI progress indicator clearly visible in the quickpick (#119293) 8cf7c12fd33 fixes #119331 d10866cca54 Fire onExit for feature terminals that lost pty host connection 7fa2b715ef0 Merge branch 'main' into joh/nbSerialize b33801c2c66 file working copy - first cut tests 8736be196db Properly join string[] profile args f68f1845d23 Move comment to the right place 2b2ff3e5e08 exec with the right encoding ede3632a560 pimp up workbench-web.html 85cf30ab517 Properly decode wsl.exe -l output 163aeeedac7 Prevent seamless relaunch triggering multiple times c64a8d59270 file working copy - use IDisposable not Disposable bae75adfb41 no more double dispose needed in _onWillDisposeDocument af10c8f65b5 Fixes #119051: Prefer fewer diff hunks 3271248da68 Merge branch 'main' into joh/nbSerialize 7902c6edcd1 remove NotebookService#destory c8dc60adac6 Use widget.shadow for custom hover contrast a07a508be8b Update distro a02fabb6d64 file working copy - dispose model when working copy disposes dfe12887da0 xterm@4.12.0-beta.3 06901e67a38 remove todo 3fd2415c9f7 Show args in profile selector 46d1ea3a2c8 fire event only when save succeeded 8410aa8f2e6 adopt name change fee37f32af6 Merge branch 'main' into joh/nbSerialize 3f71de52eef Also exclude docker-desktop terminal profile 7d99c47b755 move notebook save event into notebook editor model service, remove resolve/save/backup from notebook service and let editor model use content provider directly 06e8814b29b Merge branch 'main' into fix-95671 5dad121bcb1 Merge pull request #119315 from gjsjohnmurray/fix-119261 a255250be89 Add a user setting for "workbench.hover.delay" Fixes #117894 156fed280ac fix #119261 filter also by description in Insert Snippet 1dbcde0f1fc Fixes #119065: Handle errors also using the socket.write() callback 958171a700d Fix port process finding starting even when using output 56b55c26070 #38607 Handle uninstalling extensions a27b6f74497 implement load of the notebook model f841a70b0c0 file working copy - rename `forceReadFromDisk` => `forceReadFromFile` c8975ceaecd file working copy - remove getStat() that is only used in tests 8595f6f5d03 Update to align log level constants 23fa2860d3e add withNotebookDataProvider as strict variant of getXYZ, sends activation event, throws when no provider found c17a5ca80f7 Merge pull request #100027 from matthew-haines/master bed126ce9d7 #38607 Separete installing & installed state 6608083a3d4 💄 window error telemetry ce3ebc9f5a6 add test 391b1a6b576 Add support for `"log": "<level>"` to the argv.json (fixes #118824) d96f34c867b Fix #38607 e800c205df8 Merge branch 'main' into pr/matthew-haines/100027 b4fb4d8c2ff recognize .axaml as xml language Fixes #117298 abd1e0166e9 Merge pull request #119250 from noahbliss/patch-1 414a7eb7e06 Fixes #113614: Catch potential errors thrown when searching in the extension gallery 9710ecf1c66 Merge branch 'main' into notebook/dev af8d8116eec Merge branch 'main' into joh/nbSerialize 9b5eceb1f66 💄 4f1cdb7aa0d flaky suite for #118969 d0f2d7eee63 build e4b1e9ac57a Give room for border 0932039e138 Allow for exp modifications of getting started content 22c40603121 Extensions => Command Palette 5e0602716fe Small tweaks to styling. fb8811e513b Add "copy cell down" to toolbar 7a9844238d8 terminal profile fixes (#119267) c0885dd0c4d Add task to build extension media (#119294) b0f4dba5d29 handle blur from other browser events. 3eae316f513 more padding for global toolbar. 99dd29307d1 no layout if not visible. 6d654b9bc9e polish css. a99306b4871 Update padding for notebook toolbar & folding icon fbcd54712ef fix duplicated actions on reload. 41ecc1eda5a cell output domNode npe. c37f743a99e schedule task should check disposable again. b814edf4735 keybindings for actions. ece0761b33f swap notebook toolbar and editor toolbar. 1b52d828711 Revert "fix profile tests, path -> pathOrPaths, and exception" a5219a9350c path -> pathOrPaths in terminalConfig e9e112a6483 fix profile tests, path -> pathOrPaths, and exception 859edd7f4f0 Merge pull request #119292 from microsoft/misolori/get-started-polish 89135921788 Increase bottom padding for card 45ef6493842 Adds support for fork on push for Codespaces f8b50611060 Polish getting started items 3b3b9be7062 Fixes #113811 746c323a55a Merge pull request #118830 from microsoft:aeschli/testsinwebworker 242ddc4bdf0 Merge pull request #118400 from thebinarysearchtree/main c576cad0912 #38607 make renaming extension aware of other sources 89d8eed14f0 Allow extension authors to set the title of a QuickPick/InputBox in Options (#119144) 31a9b8f8158 Fixes #62307 14c4257e75d Fix background for markdown cells 651f0ee28a1 Simplify removal of (Default) from distro name aef8a2af5c6 Improve encoding workaround for wsl.exe 9d2478b6259 Don't name quick launched terminals a7bafc2a9a5 Add logging around port notification Part of #117790 342a55d10d7 worker eh: wrap console and send to renderer 7c4b2b09de1 add workbench-web 2ace42b0cc1 Don't attempt to create term in yarn web 9cd4712b352 file working copy - update todos 6bea69b5e2d Fix break 3a39aa41f5b Fix hiding tree hovers Fixes #118755 65fb4037a39 adopt latest working copy changes 59ee7787595 Merge branch 'main' into joh/nbSerialize 232266aaf22 first cut of IFileWorkingCopy adoption, misses saveAs and backsnapshot are improper... 2d7b64d423d add notification:hide event 9c204017ffc file working copy - remove _backupSnapshot be93116b735 Replace "Favours" with "Favors" 9f773417714 Replace "Favours" with "Favors" a23d2d40f31 Merge pull request #117994 from GitMensch/patch-1 4c9d23c8f57 file working copy 💄 adf6e065194 Fix ugly selection border on Add Port button Fixes microsoft/vscode-remote-release#4689 0b758c4e0d6 Unix profile selector (#119213) abbd77d0188 Merge pull request #119075 from microsoft/isidorn/notificationsTelemetry 99d2cb82e59 pick up notification source ID properly 5804f7dd83a Merge branch 'main' into aeschli/testsinwebworker 8af8a869dc8 Merge branch 'main' into joh/nbSerialize 3da9f36645d Cancel packagejson search in npm after 1 second c359effab04 Fix unconfiguredPortsAttributes in devcontainer.json abb6ff6d93e file working copy - dispose working copy when model disposes 733f9323a46 Initial file working copies (#119233) 970d1916421 file working copy - self register to working copy service 1902dcddd8a file working copy - add onDispose 6d02fe2cb75 fix #118945 validationMessage on extension InputBox lacked Severity.Error 943ab428d72 file working copy - more cleanup and alignments d2afd69d310 file working copy - some cleanup in working copy 111a6cec70f Don't include build files in repo 3e4c057624b Make sure we exclude ts files from published build 043a0ee0d94 Try cache busting on reload in simple browser b9f33fc242d Rename CodeActionKind.Manual -> Invoke 52201359920 Scroll the notebook while dragging a markdown cell e7f3b77a9c8 Remove typings for unused package a7ae58f4dbb Use rmdirSync instead of rimraf 05e970086cd Add missing change session events to ms auth provider b0bbf9c19ee improve pwsh logic e01b60782ae Exclude compiled notebook files from hygine 42af2c38dd2 Merge pull request #117835 from yannickowow/master 7ccf0b03c60 debug: stepOver should be alt+F11 on windows browsers 8a095f4d233 Update test associated to DataBreakpoints cf7e6f31f9c Support for DataBreakpointAccessType condition #117835 82cf09af92e file working copy - first cut manager c332b6bea79 tweak grammar 31f3f2e6195 Add placeholder text to include/exclude boxes Fix #119107 547312993f8 provide extensions sync state version api in web - reset the resource sync state when the version changes 6f0d3d5c9f5 debug: do not de-dupe same named variables fbc577e6f04 Double click to set port label Fixes #117573 Fixes microsoft/vscode-remote-release#4624 5b21b951ecf Fix Add Port row click Fixes microsoft/vscode-remote-release#4687 fc1d49f95ed file working copy - make sure to bubble up errors 03e3fce973e file working copy - first cut extraction from text file model world b335d9eaf10 Make "Set Port Label" an inline action only Part of microsoft/vscode-remote-release#4624 fdb91e27d3d Add new unconfiguredPortsAttributes to config edit a268122729d Add more docs to PortAttributesProvider Part of #115616 1c6fcca5710 Fix #115039 c9fd3403447 fix https://github.com/microsoft/vscode/issues/119157 b12279b40c5 Get correct candidate for checking port attributes providers fd57115d52c Allow for manually/programmatically checking/unchecking tasks b353f063393 comment out failing notebook smoke tests, https://github.com/microsoft/vscode/issues/119164 06ee68d4bbf api notebook update 5bb215e893b Increase spacing between tasks 26a77fb7fb8 Clean up formatting 08877abd68a Relocate keybinding rendering closes #119113 970bcad11a4 Fix bug where expanded tasks did not adjust height on layout 1bcf2a3f1dd Tweak getting started to look more like welcome 9e470ce1efc chore: update distro 0585c2e05a6 Remove experiment (#110330) ff1ce589e73 fix #119130 fc8d7681c4a Make sure katex styles are shipped under root of 581a659d427 Update markdown notebook scripts 806c22dcc91 Skip multiple tabs test for now a7006f93215 Fix potential null access f6f51117008 Update walkthrough contribution api to single object model Ref #119097 e8e6d64105b Terminal profiles (#118790) e5fc49d8af8 Fix markdown editing code cells not having top margin c09b3d2358f typescript: enable built-in 2020 semantic token support 1b695635457 Enable markdown renderer by default on desktop 83d80e8bcaf Don't try to relayout markdown cells if their height has not been set yet 772effc6e6c bind mimetype switcher later. 9063d4ac766 finalize InlineValuesProvider API; fixes #105690 9205c8bd920 Improve terminal key dispatch message 5615bb9eee4 Merge pull request #118725 from microsoft/joh/117273 a6b7fccdaab support appending per mimetype. 7af7449a295 add extension id to source of notification a294694b583 Fix padding in webview based markdown cells a7bbb5502dd notifications.test add tests for service add and remove events 99597e3974a delete cell handles multi select. b3e7d37b8df clipboard actions handle selections around the target. 562962afc9e move copy,cut,paste into clipboard contrib. 30845ba2037 Include community in README.md (#119105) 19ac5d4a5c5 Merge pull request #119114 from microsoft/tyriar/118804 9ed0aa6c914 Fix type ahead issue in relaunched terminals 7243e13db16 Fix #118818 8303d03545a aria alert for cell index changes. 5f4e9a55f5a join with next cells through multi selections 4f488a7cf21 support both selections and ui actions. 4d3df5cd983 join cells with multi cells (single selection) 881e370539e add tests for joining single cell. 3f7651fed04 move join/split cells out of coreActions. 184560bb0ce tests for moving and duplicating cells. 4855eb46a0a make notebook unit test easier. 3ee43778c50 Merge pull request #119092 from microsoft/tyriar/118066 29abc8f3499 Merge pull request #119024 from microsoft/tyriar/116022 3e05837735a Merge pull request #119084 from microsoft/tyriar/118256_test 143f4e6fa2b Merge remote-tracking branch 'origin/main' into tyriar/118066 7a6944d2d0d Add unit tests for TerminalRecorder 5141aba1941 polish 7c0e20ca4c0 Allow terminal recorder to avoid initial resize event b6921c2f2d6 api notebook snapshot 9a7366de9bd Prevent process ready log firing multiple times 32406c3f6ab Recalculate trust when workspace folders change b1359b271c5 Fix focus + keybinding issue causing input box in Ports Fixes #microsoft/vscode-remote-release#4678 0cd2ba8bddb Merge remote-tracking branch 'origin/main' into tyriar/118066 df97bc32ada Tactical fix for watching problem matcher and closed documents Fixes #116760 508b6cc7864 💄 f56b5cf7cef react to feedback b38200cf0a3 Ignore testWorkspace tasks.json 2d536914ea1 Await task config updates f0ee79acfd1 Update src/vs/editor/standalone/browser/simpleServices.ts 846917d51fd Update src/vs/platform/notification/test/common/testNotificationService.ts 77e2397c121 Update src/vs/platform/notification/test/common/testNotificationService.ts 3765294bb11 Update src/vs/editor/standalone/browser/simpleServices.ts 5da95f0e11d Merge remote-tracking branch 'origin/main' into tyriar/116022 31283f32b2c keep notebook serializer locally d1e5c8cddf4 Fix portsAttributes.unconfigured setting name And fix setting update not read Fixes #118991 e8f5186722f Improve task test layout 76cd8a00b37 Fixes #119011: Wait for the vscode API to become available before launching extension tests 1b9a61662a3 Regression test for #118256 b8476ece198 Fix task start firing with invalid process ID in dependsOn task 6fd693ec9e9 more deprecations f2761b584a4 ignore file events while saving, more logging, https://github.com/microsoft/vscode/issues/118992 9426cea171e Ports: service -> application, defaults ->unconfigured b33ce0ff5d9 Update types 2de06d768bf add INotebookSerializer interfaces and wire up IPC calls 3014c755cd7 Pick up fix for #117054 21d20148ee5 new debug setting for clearing a terminal before reusing; fixes #116699 70abcfc7689 add notification:actionExecuted telemetry event 66045febfe4 add notificationsTelemetry 45ea71d8c37 notificationsService: onDidAddNotification, onDidRemoveNotification 149a8b71c53 Workspace trust changes (#119017) e787d6e3843 custom editors - make conflict resolution actions appear (#118949) 5060cbe7bc0 Merge pull request #119012 from Daniel-Knights/patch-1 537c648fb57 mark APIs as deprecated b5eff84359d fix build b89cf5c0aff Adds RemoteHub to api allow list 4222a0981e2 debt - use product quality instead of probing for name a7f5a101589 debt - some more process and platform 💄 892a1083cb2 Fix border overlap in quick pick UI (#119039) 405d2cfbda4 Merge remote-tracking branch 'origin/main' into tyriar/116022 70a47bb275d Enable vscode.Pseudoterminals in web worker ext host 813bb397b01 update list item height on markdown cell ctor as we might already warm up the viewport. fbf1e77578d adopt multi select in drag and drop. drag the focus or selection around the focus. 84f16040107 share drag impl for builtin and custom md renderer. 12adb0178f6 test view/model range convertion with hidden cells. 51a15dee0a2 update seti theme. fixes #118912 7f43e5c846c unHidePreview should also update dimensions d949fd3bc09 Don't create markdown previews if cell is in edit mode 2f8d4892884 fix: typo d7c0ea59d23 Rename setting gettingStarted.hiddenCategories => workbench.welcomePage.hiddenCategories Fixes #118990 8e2fc51526a Remove only f390023d7e6 Remove unused 385cb56165e Fix #118953 5e09ecb9ab2 Fix #118958 83b6cdc6107 better aria label for the remote host status bar item ad428ea8910 untitledHint: introduce default for workbench.editor.untitled.hint 98d129e8b9f firefox: do not use ctrl+shift+P for show all commands since it is taken, make sure F1 is rendered 3cca5540aa8 Do no install repo on Raspberry Pi OS (#118826) c4fbdc32275 accessibility: 1000 page size as default 393adbd3971 fix #118970 61e44238a28 💄 process use 393cc7f4a22 debt - consolidate process usage cf439681f6f multicursor aria polish ae510aec2a7 no indent after 'source' tag: for #118902 fe1264b0f2f explorerModel: add toString to explorerItem for more precise error message 094274f0d1b Don't show select default shell when proc support not registered d1bffb783a5 Merge remote-tracking branch 'origin/main' into tyriar/118066 a4adb60e883 Add "Copy As..." core submenu to editor context and Edit titlebar menu (#118212) 11b1f937eb1 Prioritize port label from setting Fixes microsoft/vscode-remote-release#4542 2ac67ce84c4 fixes #118951 7a55f6fed7a skip failing notebook test 3f81fd64303 🆙 distro e8c71c048fa use %~1 in bat files c7a86c07979 🆙 distro 68a252ea778 environment - depend on product service eb90b1c59c6 sandbox - extract IPC based file service (client) and improve runtime behaviour f241e2e26ac debt - inline deprecated amd.ts methods into tests 8f1b7a36def sandbox - allow to reuse environment service in sandbox 1441ba91f0e environment - consistently handle VSCODE_CWD in all our node.js processes 56ee90e32e3 path - never use fs.promises.realpath 3d626dd868e Use "%~1" instead of "%1" in bat argument parsing. 640fa1af29d debt - use product service in more places 0e05a1f21a1 fix integration test 819cb01e0e0 make notebook integration test more stable, fixes https://github.com/microsoft/vscode/issues/118889 84fe402d655 Improve getting started page - Allow clicking checks to dismiss items - Allow hiding categories e05ab31f373 Clean up styling when contrast borders are defined a90759b5395 fix build 3006ac8e940 try out multiline extension view 5ad7633c4e9 fix scrolling body for workspace trust editor 809e11134c1 fix css for extensions grid view and settings 1a5d7f4f8ed Merge pull request #118482 from microsoft/rebornix/nb-list-focus b81cea2a350 Fix Emmet abbreviation for Handlebars style blocks (#118832) 257fbae3f34 Ensure editorContextKeyService on markdown cell gets disposed Related to #118782 e1f84e38ab2 Ensure markdown cell editor is disposed Fix #118782 216bff57715 Merge remote-tracking branch 'origin/main' into rebornix/nb-list-focus eac163c0611 fix tests. c1f954ce48b optimize scroll view from bottom. 5af4ccb87be copy cells with multi select. ad7983834af extract clone cell. 34a537bb732 sort numbers. 162d08892db Clean up 569aedce014 Mostly working seamless relaunch 7806efac02a tests in webworker EH ffdef6b9be7 Fixes #118759: Render a separate span for each inline decoration 458904ed7a3 move cells with multi select e545c0750b8 copy paste with hidden cells. 17beaf29fd5 Fixes #118614: Clear any outstanding state / requests and fetch semantic tokens when the language mode changes 8ca6a56d467 Try restoring ports more often Part of microsoft/vscode-remote-release#4551 d7622d392b4 change back untitled hint default to be hidden edf387a2e8f run filename through realpath because it seems nodejs isn't always doing that, https://github.com/microsoft/vscode/issues/118812 1c9e7eb296e 💄 5a8936ae639 Lift native text file service to electron-sandbox (#118815) 1bb87db91d3 debt - provide groups merging from service and add test 0b4915dcea2 Change portsAttributes others to be its own setting 61fe79db654 Remote indicator for folders and workspaces from contributed file systems. Fixes#118813 55bfe8c2167 Merge pull request #118766 from microsoft/aeschli/extensionDevelopmentKindSimple 5109a52b2a6 explorer: use findClosesRoot in select() 3aca77c0161 Merge pull request #118777 from jeanp413/fix-118557 3eae8534747 fix #117093 update Filter on Type indicator after 'list.toggleFilterOnType' command (#117099) 9d220a95c1c Fixes #110885: Have `--max-memory` also be applied to the extension host bd74e2fb6a0 replace openOnFocus with selectionNavigation 5f451c6670d Merge branch 'main' into aeschli/extensionDevelopmentKindSimple 1f22e55badd sandbox - share most desktop.main code d6d2910b96b sandbox - use actual workspace and config service 1dce5d35536 replaceCells as a single edit. ebc6eade483 update prefix sum always when edits happen fe9466a6e1d false negative hidden ranges test 4f5824ea28b enable async tests. 3dff030ea14 delete folded cell would not change other folding states. 5e2f573d1dd cut multi cells w/ folding. 06b54543d66 Comment out a few error logs for now 498449fa8c1 Remove content version logic from webview 02d3ca91dc7 Make sure we update cached version when cell changes 544b117130a createMarkdownPreview should only create previews, not also update them 1e92de9921e Log errors and remove unused method 574740fed37 NotebookEditorWidget should not have to know if a markdown preview already exists or not b5e22e7ed43 Remove extra log 6ea4b1cdc1a Add version to MarkdownCellViewModel 97314005fca Revert move change and disable debug flag aeb8f3811d6 Avoid re-rendering markdown cells if they have not changed 4b9d29ae6b4 more polish and re-use extension grid d5f47dfb885 Notebook custom markdown renderer optimization (#118288) 3635f113876 💄 b4ebf03316c selection tests. 0dcf9300ddf Fixes #118557 e9b7b5d25b8 configure extension kind of extensions under development 63d6e0c008a adopt selectionNavigation. 46fd12b0a91 align selection and focus if they were both empty d31566b57f4 Don't include css in main katex bundle 8627fd1f883 Merge pull request #118753 from microsoft/alex/extension-test-running a97990c9713 sort indexes in cellIndexesToRanges 919292a6742 Merge remote-tracking branch 'origin/main' into rebornix/nb-list-focus ae4ffb1b81e Handle extension test execution on the UI 52ab2fe123f add Education extension to category constants (#118589) ac0008a25b8 Remove waiting for welcome page while we are experimenting with what the welcome page will be Fixes #118748 8f8321d638d Smooth relaunch poc d574f8e9163 remove duplicate code 63460db67ea Fix #118741 d5e4525830e Add comments to add java workspace tags to GDPR inventory (#117740) 1ad8c467972 Merge pull request #118574 from microsoft/tyriar/100709 5afac656035 Prevent double attach to pty host listeners ba8f0fff7ca Remove logs b92b610e861 mark isEmpty as readonly f2515c57a4d Fix repository link for vscode-references-view bc405e936fd Try new CSS grammar Fixes #115480 244428dfa7a sash: workbench.sash.hoverDelay setting 10fc457d699 💄 sash f8ce2745c05 add stdout and stderr mimetype, add renderer for stderr 97efcde244f Merge pull request #118664 from microsoft/aeschli/extensionKindController 3fb39ad72d6 fixes #118694 bd84f143797 Merge remote-tracking branch 'origin/main' into tyriar/100709 37a826fe75d Open Recent goes to wrong workspace from remote. Fixes #118683 6af126bb3ce Move to writeSync instead of writePromise 49cad9a1c0d Fixes microsoft/monaco-editor#2382 0740b4a3134 sandbox - move platform limits to common fdd57917f30 don't mixin default metadata when "replacing" notebook metadata 9a982d0049f fix configuration caches - respect scopes d7854c3914c Remove unused 8788d628814 First cut of moving to hybrid getting started/welcome editor 9b2ee7fb7d9 Reduce size of Katex bundle da3cbe74dce Avoid extra postMessage call for iframe based webviews 8fefa6aff22 Speed up mac builds (#116984) 984479d1792 Fix not being able to run a cell when it is in the Success or Error state 07d02d3e2b1 use new icons 638926d5b5d CES experiment treatment 2d7fdd82ec8 update connection state before reconnections f3f1c131385 Update Codicons: add trusted workspace icons1f495f5857b1b80801806 Avoid some calls to `.then` for iframe based webview post message 5b5dd906551 Fix manually providing PAT for GitHub auth, fixes #118675 11d5e82c80c Fix any key causing shift+tab focus change c72d7612b41 Add an untitled document data property (#115790) 371562f630b move trust color tokens and update values e679983a3fc remove border, use color icon, use link button 1f2313b4a2d Add back custom editor test workspace 0f6d7c41eb5 introduce customEndpointTelemetryService 268c0d04a66 fix #118578. offsetHeight to include padding and scrollbar. d1db6f0efef notebooks: update output to match NodebookCellOutputItem api 7cae7b5cedf add ExtensionKindController a2b5e58b091 remote authority - update comments 75da06499c2 #101995 extend tooltip of menu item that defines 'alt' command (#116211) 3ac310d1cf9 Remove icon from input row in ports view 3dc05e36e15 list: anchor trait 913a5949445 cleanup debugHelperService f1f830aefa2 Fix User tasks only working once without folder Fixes #118370 27ce1eb630f list, table: selectionNavigation option 6be4a142367 fix https://github.com/microsoft/vscode/issues/118609 8fd24025701 :liptstick: deep freeze notebook events before emitting them 6c6db188b7a polish, avoid classname.split('') f0c44394d11 Merge pull request #118433 from microsoft/aeschli/openWindowsWithAuthority 637b659e4ad refine NotebookCell API afe0e2b9a77 Fix regex port attributes over applying 278a41c349b Show Open Preview in Ports view for public ports a6d7d86e857 remove `viewType` from openNotebookDocument call da562fa27c5 Add regular expressions and "others" to portsAttributes Fixes microsoft/vscode-remote-release#4623 b3e6307430d polish 1422de11110 sandbox - move performance.contrib to sandbox abea343c10e fix https://github.com/microsoft/vscode/issues/118369 b0f0b6125dc implement review comments 23e0d141edf Update src/vs/platform/windows/electron-main/windows.ts d383642ba20 Update src/vs/platform/windows/common/windows.ts 78224b9b9e9 refactor perf contribution so that they can be inside electron-sandbox, https://github.com/microsoft/vscode/issues/111211, fyi @bpasero f83b2f46dee shell env: add more logging 1d6241a8a08 prefer ReadonlyArray<T> over readonly T[] 94303f8e574 build 256ce60286b Bump elliptic from 6.5.3 to 6.5.4 (#118478) 623075e0962 update distro a713ca6204c Merge pull request #118596 from alienvspredator/main 420f8dde79f debt - more layering fixes f0321e30875 debt - layering fixes 9d8042db309 more jsdoc around workspace concept a19fac2442c better docs for #118566 96fabf5cf95 fix #118591. 6d079845776 fix(typescript-snippet): fixed "newpromise" snippet 1d686afe81c reduce grace time of remote terminals (#118571) a9087e9d0a9 Try to avoid extra promise chaining for posting into a webview cbacbe647c3 Fix markdown preview still being rendered while in edit mode 54f30ed19ce Lock to commit rather than tag for Azure login action 3244facbbbe wt editor stepping stone - make extensions list better - centered header style d4ee684c8de testing: show progress in status bar, minor refactors and cleanup 80112e79ffb testing: show total number of tests to run 5b41604444b testing: add more logical default autorun behavior 7a9e144ee15 Fixes a listener leak with ILanguageSelection 57155e84203 Fixes #118195 - avoids update if already set bcb8c8a4f4b Remove notebook document runnable metadata #106747 8454701b67c Update test for api 225a8c2b89d Infer cell "runnable" from notebook kernel state Fix #106747 7a19d09047d Begin eliminating cell runnable metadata d1164661d29 Fix markdown edited cell height on reload c77e5ccd947 Add back top margin for webview cells d299be88ea6 Updates proposal for #116906 556e6d8310f Fixup search smoke tests 58bd8e075a3 Fix spelling in comment ba54c76164b Use TS replacement span if returned 724bc08f906 Remove log f2d687752c9 Create a new pty ready promise on relaunch 65e4309c0d9 Directly expose environmentVariableInfo 37c54c79e0d Fix compile 7f94f0d97c2 Move some ptyProcessReady usage inside proc manager 3cc479953ca fix #117718 fire onDidChangeResources event after unregistering group a7c9230fb33 Update distro d6f4353fae4 bump distro 9eceb504987 Move label about for #115244 after more tests are failing f8a6f90dea7 Revert "chore: bump distro" e5a10ca55d6 Skip search tests while diagnosing flakeyness 88655de6104 Adds logging 6922f6150d8 xterm@4.11.0 Diff: https://github.com/xtermjs/xterm.js/compare/a73fe62...4.11.0 79e2119c5e6 Revert "snap: set compression to lzo, #117852 (#118116)" 43ced8a10a3 chore: bump distro 0f042b2c856 fix https://github.com/microsoft/vscode/issues/118569 0e43220113c finalize telemetry enablement api refs #110267 95d3c1e63b7 finalize isNewAppInstall api refs #117058 e60b94d6e9c Merge branch 'main' into digitarald/ces 6438e0564af Add 'Marketplace' as option for file on and remove as top-level type, #118473 17c67963f32 api work snapshot 112bd090027 Queue file operations 4ee2ef41e5b update cache on reprocess 0f64ef1b655 remove NotebookDocument#contentOptions f0cf34e073b debug: do not bind F10 to step over when on web eaf4a6a91b7 Fix debug console URI being decoded (#118226) 417b7803a18 Update distro 2c11dafcc2f Merge pull request #118252 from microsoft/tyriar/116467_2 dc92ff53548 Set distro back to that in main 4bb960ade60 Merge remote-tracking branch 'origin/main' into tyriar/116467_2 b02e102f480 untitleHint: use expereiment service 90efd0a81aa Update README.md 449158a1aa7 Some Ports view cleanup b8a320867e5 allow null for remoteAuthority in IBaseOpenWindowsOptions to force local window 637497076ac Update distro 1e7fbfa7674 Merge remote-tracking branch 'origin/main' into tyriar/116467_2 e7b0596d89a Revert "Comment out notebook compile error" aaf6287eccc remove skipped test e96f0ea3700 todo-tag 7bcec044268 Comment out notebook compile error 878526839a3 Update distro 364b9e98e83 Merge remote-tracking branch 'origin/main' into tyriar/116467_2 ab9e11f38e6 Remove resolved comments e2ba7c6ae30 Breakpoint inline edit button should be a submenu 27efd88041d Remove preconnection terminal concept 4db71714ebd Properly dispose everything in tunnel view cells Part of #118544 9cc276648eb remove onDidChangeCellLanguage-event in favor of the existing document closed/opened event sequence 55af8021a12 Simplify RemotePty, revive shell config cwd e373b9c59e2 Focus row when escaping input on Ports view Fixes #117771 3c96cb6254a Merge branch 'main' into aeschli/openWindowsWithAuthority 99e97da512b revert unnecessary change d1dbb93317a Remove remote test failure comment 6d01ad952a9 Merge remote-tracking branch 'origin/main' into tyriar/116467_2 e15767f6dcd add comment for remoteAuthority 5ce792fcfad Add SECURITY.md 98a22a957a2 declare cancellation support for openNotebook and wire it up, exempt notebook content provider from provider naming rules 0e04c15de4f assert unsetting of active notebook needs null, https://github.com/microsoft/vscode/issues/118470 bcfcb539ab5 unit test for https://github.com/microsoft/vscode/issues/118470 8c436826ae5 Merge pull request #118471 from DonJayamanne/openNotebookBug 30d699fa104 on fire active notebook change event when something changed, https://github.com/microsoft/vscode/issues/118470 425316c3764 Add a compose language (#118042) 63be79e67de Merge pull request #117062 from NotWearingPants/bugfix/rtl-cursor edfbf27e3af #118443 - change name fa6d38a99b3 change nls ids 9d3a1d9f59c Fix #118443 6b76fcb671e Merge pull request #118468 from spetrescu/main 7d96db1e51b Make underlined link buttons blue to match the styling of similar buttons 27975dad4fb move to IProcessEnvService where appropriate in default shell logic (#118271) ac229ced073 Revert "Reenable smoke test to see if still flakey" #115244 09c3c2d3be4 Remove broken part of test 11a84a6e8ac inset -> output. b62e3c7d1db Update distro 5fdbc82111f Re-enable task and term test 9878ccfbd74 remove markdown preview only when it is hidden or deleted. 250c7baf7e8 Fix #117903 c870a55b708 Update terminalProcessManager.ts 8fe29a7c415 Uncomment in test 30f41631849 Skip the failing test for remote only d89e8cd27ce recent entries with authority c59c1101162 revealView should scroll a little to reveal items below viewport. d4f8348c6ac Handle undefined extension publishers in issue reporter, fixes #118480 61301530c69 revealView should scroll a little to reveal items below viewport. 23ad719498b Log acceptTerminalOpened bdbf5850127 Bump vscode-emmet-helper, fixes #118363 0e8fba32637 Add outline offset for view actions (fixes #117349) 9b1700a8291 example of notebook specific navigation commands. 2c1037d3521 Fixes #117600 (#118397) b20839c1f3d Add 'Marketplace' issue type to issue reporter, closes #118473 a8739f9c3a5 Change messageDisposables to DisposableStore 2b9470cb4e1 Clean up SearchView link button code 31a7757fc7b Better "Open Settings" option in search view 18f16643ead Add button to reenable search excludes Fix #115352 244e9e6e793 set remoteAuthority in NativeHostService.openWindow if not yet defined 1761ecec3bd reduce selections. b6b9aa15ef6 debug: allow passing partial config to start debugging command 221e20b3742 Re-enable, add some more test logs 7e6d4c5eb91 debug: fill in selected configuration by name if not provided 3f56118e7bb move cell up a39e7343653 Oops 584999658ee Bug 820f0eeb270 Fix tooltip not showing for codelens extension a0c8d41f9ed add notebook navigation commands 78cb4cfc32b improved comment for InlineValueContext.frameId 3df01b4ae74 Include ms in shutdown constant comments 45c032da7ab Skip the failing task test 1469a82540f fixes #118006 d8a7202293c Update distro e22c2be14d1 snap: set compression to lzo, #117852 (#118116) 03c8548523f Merge remote-tracking branch 'origin/main' into tyriar/116467_2 9022c7fa945 Update distro f2cfdcf19b8 Bump distro 4a82fbab162 Don't force create a terminal on no reconnect 06044789bfa API proposal for PortAttributesProvider (#118446) 3f778f6aebf Update distro 9c78fa40ca7 skip failing test (#118443) 20b19612917 Move proxy resolution to vscode-proxy-agent (#117054) b41b95faee9 Pin windows-process-tree@0.2.4 to match main package.json 4d3b1580233 Disable terminal tests in remote again, fix settings for tasks 1cd624c12a3 Merge remote-tracking branch 'origin/main' into tyriar/116467_2 4abc244a97e Add windows-process-tree to remote deps c2a92a1ba67 Merge pull request #118418 from microsoft/ben/sandbox caed3ea183a Merge pull request #118269 from davidanthoff/julia-indentation-rules 007baec8d51 fixes #118214 (#118425) c187999ee44 Merge pull request #118310 from smorimoto/ocaml 2a0f9aa8dc7 Reminder to compile between tests 69d36e8c982 Fix transformToSnakecase 305456c873f bump distro f7274905565 editors - fix mergeAllGroups (#118268) 8c3a00f78cb allow debug textmate in sandbox (#118219) f74d3b2fc75 fix tests 0c17e384499 sandbox - migrate backups from md5 to our hash algorithm dbe9dd49675 sandbox - make signing and integrity available 3f46e7f7b59 add ui flag to mocha tests 74532eb261c Re-enable process unresponsive checking 5cc1775bbf0 Disable unresponsive create process 11897d00a7a Disable pty host listeners temporarily 074632a51f1 Try enable remote terminal integration tests 508fcfbb537 Add more OCaml related file extensions to the OCaml group 5d80c30e5b6 Reenable smoke test to see if still flakey Ref #115244 74014e7fc6d Fix #117251 fe79bb261fb Add defaultSnippets to getting started contribution point Closes #117476 2d5e9cae4e0 💄 d3086eaa8c5 expect commands to set selection and focus for us properly. 7707feab17b accept focus from the list view. 6e83ba82107 fix #118279 da79b9db816 Don't setup pty host listeners twice in remote ea5f05a4358 Trying to clairify how webview options are used and passed around e066c74761e Document new fixedChunkSizePolling ts watch mode d7d42534260 Mark field as readonly a01035c44f8 Pick up latest TS 4.3 for building VS Code 02a5d5925ba Disable relaunch in tests 755fae50ab5 Bail out of create process if it's been disposed 2d3f1a0b478 fix #117699 258ee03bfbe Update distro 3483e9541b2 update betweenCellToolbar actions per context change. 61ea6ad847a Remote shell type support fc677cb3220 fix #118273. c40b367840d Merge remote-tracking branch 'origin/main' into tyriar/116467_2 b15bbfa8516 More test logs 3e345101dfd update shellType when it changes for local windows terminals (#117998) 6b2daa9a897 Update distro ff09362f443 Merge remote-tracking branch 'origin/main' into tyriar/116467_2 5d5fa588828 Support pty host management in remote 29b1fcffd1b fix #117684. 7af259ab841 Add logs to test c24bfc336c2 💄& localization daf840b9293 Revert "fix visually background flash of cells." 016b809eef0 kill terminal process on ipad (#118247) c18378655bd Add Julia indentation rules 7f7e427d3ba fix visually background flash of cells. f704f80f877 Pick up TS 4.2.3 22cb8ccdac3 Merge remote-tracking branch 'origin/main' into tyriar/116467_2 a7d9285b89f Update distro 2e68f2ae918 Better fix for #118235 00d3831d0c7 fix #118248. 59972ff745f fix build 5144d664926 dedup ansi color rendering. bba6d12ccb2 💄 ff5da2ff172 DOM.show/hide. d2e39d0ae09 use resize listener for all main frame outputs. 32f7c1d93a8 Don't assume uncompleted category exists Fixes #118235 ccb3601d552 Support term cli commands c2e3a4cdc67 Update distro af0ec1caa0b ctrl+c on ipad (#118243) 6799395da0c Revert "fix #114009" (#118242) dfbc5374637 Increase local grace time to a minute fe24a792b03 Support attach to session in local f916e9f1aba fix #114009 df6b2691705 Support orphaned processes 48be13acf8e Check if VSCode runs serverless (#118233) e518e533653 Share IOffProcessTerminalService 51e773e69f2 Merge branch 'main' into aeschli/openWindowsWithAuthority 0bcba0486bb Make setTerminalLayoutInfo interface consistent 7703dff5fc1 Clean up, bring local remote interfaces closer 92ad349125b fix typo in comment aadc16a2371 Simplify channel comm 230e0fdc9aa clean up, some ground work to support viewColumn, $acceptEditorPropertiesChanged must update all state before sending events, remove active notion from notebook editor 9516844abfd use TS typle naming feature 68a6f1c30e4 look up editor by id, slimmer dtos f7ff53d7b06 Remove `_wrapWebWorkerExtHostInIframe` 418b8248e43 Progress towards sharing local and remote term impl 25dc50c18ed Remove start-up timeouts 49b5e3ba0ae bump version 978d1399f54 Fix compilation error fca9c7f78fb Fixes microsoft/monaco-editor#2375 5931e598b10 Fixes microsoft/monaco-editor#2344 205ec8c5f2d Fixes microsoft/monaco-editor#2358 b2a0913ad23 Fixes microsoft/monaco-editor#2168 9748b5f3c0b Fixes microsoft/monaco-editor#2359: Avoid syntax that confuses webpack less loader 5c4663baadf Fixes microsoft/monaco-editor#2355 60222b710d4 Align `MultiEditorAction` with `MultiCommand` 453e2793b2b Prefer using TS constant defining the context key 04770364fdc #118222 skip failed test 1260de1c101 sandbox - move workspace tags to sandbox 17212ee46f8 #118199 c024db9f419 NotebookEditorSelectionChangeEvent should contain selection ranges, not cells 2e84eb92077 explorer tests: use strict equal 1e28c1ec7ee debug tests: use strict equal 1a9df6127cc fix smoke tests ef6d44f53aa debug console shouldn't collapse messages when they have different source locations 6e5e1e700b9 api todos 6117524374f make NotebookCellData and NotebookData classes, rename NotebookCellData#cellKind to NotebookCellData#kind 86df4442128 remove todos 3a21f7815c4 Merge pull request #118125 from microsoft/sandy081/keybindingsEditor/adoptTable 57aaafc72f3 Do not check for settings sync enablement while initializing in web d4b5298cd62 -add bg color to even child - clean up 997c9f29307 add showNotebookDocument overload or uri ae2f3e07e12 streams - add test for using error as data be70750f862 comment 💄 b65719bfa27 streams - require explicit end() after error() and remove error support from end() 188e6aac851 stop the code bunny, reuse the createAndFillInContextMenuActions-util, fyi @sandy081 @rebornix 7386525c683 remove one more occurence of '1_run' bc62648b05c Revert "Remove authentication provider package.json declaration" fead22bae42 bump distro eed8a79e81f Extract proxy agent support (#117054) 79096af4755 use CSS for odd styling 223f4f820f8 multi cursor: announce cursor changes 3b05017bb8e more 💄, more strict typings 1d8493b203e 💄 in mainThreadNotebooks, return types, more private, dispoable store, duplication removal, etc 81edf8b91ab Merge pull request #118071 from mtaran-google/main 85c1a17b60f Merge IEditor and INotebookEditor, move editor things into notebook editor service fc785836967 fixes #118006 d84ddcbd529 Open window with authority 39c1d680867 #62531 clean up 2dfc39c6949 Remove arrays#mergeSort because by now browsers support the refined sort spec which mandates `sort` to be stable. 587274078c1 remove NotebookDocumentMetadata#displayOrder, https://github.com/microsoft/vscode/issues/117684 3e8b0eb2d4f remove displayOrder from NotebookDocumentMetadata API, https://github.com/microsoft/vscode/issues/117684 afae25919a8 Merge pull request #115351 from gjsjohnmurray/fix-62531 fa37b721d1e 💄 ddb17dc1282 💄 dbbf2b16882 shell env - introduce a service to resolve shell env as promise (#108804) bd2b229870b debug: update js-debug 567b82a0f9c Reduce padding of new markdown cells in notebook 38ac13bc833 Slightly reposition the folding indicator for cells 99f2b830a1d Improve drag and drop indicators for custom markdown cells in notebooks 354a0a2620f Disallow dragging the outer markdown cell for rendered markdown cells a34ed4b0d7b Make markdown cells span full width of editor 60d600b3661 Fix showing wrong name for files in search after rename Fix #117778 1c7ced625a3 Update dimensions of webview element when it is shown again 72995bcb80b Mark property as readonly array 28b7345808b Improve documentation for WebviewService 9fa1800b979 Make the webview icons manager disposable 5bff5459d13 Move webview icons from generic webview service to the webview workbench service acdcb64a6c9 Throw error if a webview is double registered 487296741f5 Don't require lazy webview to be passed to WebviewInput 344f329dd42 Make reviveWebview take an options bag instead of parameters 79ff1ec91bd gate on feature flag aca4cb12985 workspace trust telem 0f975049421 Fix output padding/margin for diff notebook editors 9f395ddb934 Update Codicons7e0f3778910eca51a2dad Mark selected markdown previews in notebooks (#117947) 191d3324132 Add offset to button focus (fixes #117909) 8a81f4149d3 add warning log if webgl cannot be loaded 6abc478020f Update src/vs/workbench/contrib/terminal/browser/terminalInstance.ts 8b1ddde4f5b move disposal to end so measureRenderTime gets called 920b8b31931 store suggestedRendererType to avoid retrying webgl if it's thrown an error unless the setting gets changed e9a748131c1 use storageService bab447271a3 measure render time if webgl throws and canvas set b619d92639d use canvas if webgl throws e7ce70318ff after webgl is disposed, don't retry to enable it unless the renderer type gets changed ca83d009f37 Update src/vs/workbench/contrib/terminal/browser/terminalInstance.ts d61adbfd923 part of #106202, make webgl renderer default, using dom if loading the add on throws 1e5e33cd023 testing: fix unit test err d6b3bc68f1e testing: move types to classes instead of interfaces 35aed337263 testing: improve RequiredTestItem api 1370dacbe0f Rename localPtyService to ptyHostService 05ccfc4fcb7 Move localPtyService to node db06103f1bd Enable search in open editors checkbox by default 597c5958527 fix overflow in command column 0150b020a10 Merge pull request #118121 from microsoft/tyriar/116467 2d4e671f730 update distro. 5b2865bc99b fix layout - do not consider header height c6202bb3cc5 Adopt to use new table widget dd3f3f9d7fe Update issue scraper to use standard bot PAT and run every month 8465489bbd4 Fix unit tests 8fd1b977166 Merge remote-tracking branch 'origin/main' into tyriar/116467 12ab47ff863 Fix compile c9ae209c80e Use safe process env from electron-sandbox 97cb1ff41d2 Register ILocalTerminalService 468d73edeb0 Fix compile 306bebf0f15 Move responsiveness check to local terminal service 3a1f4c402b4 Move terminal instance service methods to local terminal service df863f912b3 more context key doc 5ba5f986b92 remove notebook dependency from build edits 128e9b502d2 add frameId to InlineValueContext cb7ad05cb7e Merge pull request #117766 from microsoft/tyriar/remove_flow_control 73fee061714 Update distro 9bf3a06e647 Merge pull request #118118 from microsoft/tyriar/117990 68a3a7bbf9b improve comment 0ef6619a3eb services - use refineServiceDecorator for environment (#117881) 1e0d5009b5d fix exception breakpoint padding 03681b39a50 Update distro fa4c3c6cf1e Show ports badge on view, not view container Fixes #117904 a5c28d0ca06 Merge remote-tracking branch 'origin/main' into tyriar/remove_flow_control ddd6fccfee0 services - use refineServiceDecorator for layout service (#117881) ffa703d4805 Recover on pty host reconnect c0f6549d1cb files - address #118060 on master 94dec183740 Fix simple file picker not opening entered value Fixes #116858 7586d1a0fc2 Fix extra http on some forwarded port addresses Fixes microsoft/vscode-remote-release#4595 fb46801cf2f lock file-changes-action dd14e280254 Don't use an icon on the Port add row c2a2cc2bc3b Allow quick input to show info severity (#118032) 179c89852f7 Change icon for npm scripts view Fixes #118019 3c238e71dbc Add "hasPackageJson" check back to npm view and let it find files in directories Fixes #117950 1d46693af84 fix IThemeService decoration ids. For #117881 31012ea2d4a add refineServiceDecorator, https://github.com/microsoft/vscode/issues/117881 978b0d6ead9 context key doc 16ea2f2894b remove "getter" wrapping for proposed API types (classed, enums). These checks needed to be disabled because of an TS issues f79a0df4dbe api todos, remove long outdated proposal 01d775756c7 todo goes issue b6141474a76 move undo/redo and clipboard support out of notebook service so that it slims down c349764ab2e no graceful, throw errors when trying IO on notebooks that have no provider, move notebook model things together 069da883da5 Merge pull request #117834 from jeanp413/fix-panel-codicon-outline 8025d97ece8 mark `displayOrder` for removal, https://github.com/microsoft/vscode/issues/117684#issuecomment-790019754 73c01a5dd87 Merge pull request #117424 from atscott/dedupereferences f43fcbe6a4e fix https://github.com/microsoft/vscode/issues/118103 62d6a24efb9 revive URI when receiving them, fixes https://github.com/microsoft/vscode/issues/118085 0657df6e82f fix some area labels in extensions and scm 534e2306379 Renaming a folder adds it to history (fix #118080) 2ba67b7b075 Allow ripgrep search provider to work for files backed by file scheme, but not file scheme themselves (vscode-userdata) (#118069) 5f17dc2a596 Ensure that PrefService calls openEditor with a proper options object and add tests Better fix for #117952 54758b7e16d Revert "Ensure that PrefService calls openEditor with a proper options object and add tests" 2ae55bc7164 Ensure that PrefService calls openEditor with a proper options object and add tests Better fix for #117952 16c94f18258 Remove incorrect command a4b2541e379 Mark disposableStore property readonly 584d2338870 Use `_register` for disposable 538931e7906 Make sure context key listeners are disposed of 49d05f998f0 Add `CodeActionTriggerKind` api proposal 20f06e04445 Clarify docs on CodeAction return type 7e18b7006d0 Use generic type for CodeActionProvider ba117e60c20 fix #118043 4bd99a42df0 Fix old markdown preview not being removed on drag 4371e72fb6a Fix potential null exception while dragging cells abf99de040e 💄 aaf70523a8e Bump vscode-emmet-helper, fixes #118008 828f99eff55 Update diff editor with new webview options e56182e67f2 Make the backlayer webview span the full width of the notebook editor (#117948) bfa7822f703 Fix typo in IWorkbenchExtensioManagementService e9533c22fee add basic workspace trust unit test 19b7444ccf0 fixup! fix microsoft/vscode#117095 de-duplicate location results 17f63a649ec testing: update to more proper provider api 2f7438f492f Fix spelling for type 5d5b9dd0a8b Don't label non-editable custom editors as readonly 5f24ec84ac7 Use correct new context name 6949fed6ed2 Update grammars and fix julia update script for Windows 0e94794c9d0 debt - remove unneccessary indirections from notebook service 09149ac0930 Avoid double dispose of pty host client f80f0d7074e More forwarded ports trace logging 65c0eeb03d0 fixes #118006 a24cb4615a1 debug debt: remove unneneded check 341c130b0e9 call stack: get rid of actions, menus everywhere fd948827992 Deprecate editor.accessibilityPageSize setting 79cf4e92ce1 Use Promise instead of event 14fd07d57a2 Workspace trust api feedback 65a9aa17768 Use "(Settings) " as a prefix for userdata paaths in web Closes #114979 c3d7bd2269d Reserve space for recent list to prevent shifting when it loads Fixes #117628 e21f3916af7 Focus first uncompleted category rather than whole document on start Closes #117540 09dae2618ae Disconnect in debug toolbar should dispatch to root session 8c13b011133 debug: simplify registration b6f87905932 💄 comment 4def740615b wrap perf stuff in iife, https://github.com/microsoft/vscode/issues/116546 bc444ac3797 Fix #117869 bede292addb Error on `remoteAuthority` in Local Workspace File. Fixes #118023 6b3313141de make sure local dispoables are disposed and cleared, https://github.com/microsoft/vscode/issues/117675 d13b7ff3641 one class, one variable style, https://github.com/microsoft/vscode/issues/117675 2e9fde23fdd add todo-tag for InlineHint, https://github.com/microsoft/vscode/issues/105690 0a49559a443 Mitigates #118008, better fix TBD a795f49b097 more enforcement of readonly nb doc. 62cfd68c779 absolutely no polish POC feature list d82bb46c445 do not prompt for confirmation in editor ed94b5d7562 allow text selection of description 6979a39169a move webview resolved state internal. c113b806cca re-organize notebook editor widget methods. 1614e28a11c remove notebook editor widget methods not used. c70fb23a27b 📓 move decorations out. 52bce12c25e testing: fix up wording in api 25b5db4d55c testing: make workspace test hierarchy required 94cda08af53 testing: make runTests required 9fbc8811428 testing: make hidden state more clear 2cc1a8061d1 Fix VSCode spacing cf3faa40460 Don't relaunch extension owned terminals (#117987) 6c6caf678fe Don't force kill ptys on Windows on window exit 7b91cd85284 less exclamation 6643b5e520b de-dup: uri. 0eb8c53f90b de-dup, NotebookEditorWidget#willDispose, didScroll. 623741272a2 Add activeCustomEditorId context 08ceea18aa0 rpm-spec: fix the wrong claim about working on EL7 e3829dc2477 Add 'prune' option to fetch in git extension API (#117923) 975dfff6db6 Emmet: Change the type of emmet extensions path (#117946) cc5db258239 testing: fix NaN if 0 tests ran fe353a54240 testing: close error peek view when test run starts 7d1751444b2 testing: fix tree view overflowing container b6251fc0baf testing: fix 'run in current file' running all tests da98cc6e94d testing: fix run at cursor discovering indefinitely 7c1305782b1 testing: adopt new autorun icon 4a6488c6d03 Move kernel/execution code out of NotebookEditorWidget for testability b629d888ca6 Bump Emmet yarn, fixes #117154, fixes #97632 5073e6f1fe5 fixes #117968 f97dd62ece6 Make sure we use the cannonical uri for file move target 1155803d134 Use case-insensitive check for file extensions bb8b693479b Mark properties readonly 20ec5b80085 Reuse generic open with logic for custom editors 75b5207f850 Extract BaseToWebviewMessage interface 4e4c43f30fd Update distro e994e5ab498 Persistent terminal id -> Persistent process id 647773d7e68 Rename terminal id to instance id 88d9e2b46b7 Refactor second task test f8c41a80b0d Refactor first task test c8fc575275d Ignore terminal events not related to task test e62bf133c45 fixes #117575 15c02651811 use one element for focused/active item in actbar fixes #117584 cd9ce538ba5 Add shouldPersist terminal tests c6d6bda7197 Merge pull request #117974 from ko1/patch-1 20096095f19 fix extension readme not rendering img width height (#117961) 2b50ba174f3 refs #117960 5d4377de987 March for API issues 72de8e9be86 add region markers to isTelemetryEnabled proposal, https://github.com/microsoft/vscode/issues/110267 ff225b9fcce add telemetry enablement api (#117944) 4de8cb29073 increase accessibility page size to 2000 9692037daa9 Update vscode.d.ts 9e4520310ed Fix remote terminal reconnect 85cbc2bc7ce cancel parameter hints when editor blurs, https://github.com/microsoft/vscode/issues/115265 44955421ae7 fix https://github.com/microsoft/vscode/issues/117431 7bc94131f17 change anyScore so it repeatedly run fuzzyScore on substrings of the pattern, https://github.com/microsoft/vscode/issues/116683 0018625d00e more details in explain dialog, https://github.com/microsoft/vscode/issues/116683 e2c5ff9db00 do not auto open pasted file 2022aede921 Return early on promise reject. ed1118b27b1 Support empty messages during location import 58ab537f4fc Debt: descriptions/hide context keys (tree, ports, tasks) 66b7ffaabf9 simplify $tryShowNotebookDocument further 65e28321240 use label service to infer name of notebook input 83f40886812 notebook - simplify group/viewColumn handling when opening a notebook editor via API df8763cfff7 api todos for notebook cell be11cb2de00 disable failing test (#117446) f70433a596a fixes #117910 73f9f126fb2 fix tests 932c7e247dc 🆙 distro 8c1bfcb569a services - distinguish environment services (#117881) 5510ee9c51d services - distinguish layout services (#117881) 6c13c8f4ed2 de-deup: getContextFromEditor. 9f7d229461a Extract decorateFileEditorLabel to a common function d7f90c7dbcf re #114554. d9d5e5d9c38 Merge branch 'main' into digitarald/ces e3bc5abc511 Draft for ces survey 400737c5b89 Pass 'data' to completion details request (#117092) 5d6ea08985d fix #116751. 01025340392 Splits clone/docs welcome Allow GitHub Browser entry in the middle 015ca030c4b tests for selections for navigation and hidden ranges. 177e3474c5a consolidate index/handle update api. 1f08b8f9024 wrong use handle/selection 460ebdaaf5b Aggregates welcome view registration by view id 9d071596951 debug: bump js-debug-companion version 811dc8d45a0 Remove authentication provider package.json declaration 8e37e4722ec Fixes #74505 (#117807) 5aeafe2b209 Fix Emmet issue where incorrect abbreviation is displayed in an html document (#117759) b3ade044793 fixes #117924 0c9476a0b6b testing: fix tree not updating if nodes are replaced with same id f18a3400668 Use method instead of event c30e2d46b2a Fix emmet update extensions path issue (#117797) e4a69193d04 Merge pull request #117138 from shskwmt/fix/116822 a13f7ee916b actionBar: home and end should navigate to first and last item respectively 721514f2c1d Merge pull request #117832 from jeanp413/fix-117354 98883cf3b11 remove actionBar.reverse orientation 0bf5569f02c seti: use CONTRIBUTING c3e2c76f762 add failing, skipped test for https://github.com/microsoft/vscode/issues/117899 edadf1c7194 Implement shouldPersist for all terminals processes 884ed1e3f33 Use initial instead of unset b803df2435c Fix top shadow issue 3559e47c08d update gulp-tsb bf894811515 Some Ports view clean up 73112daff11 Remove extra check that is not needed e9166375289 tests - enable color output for integration tests 32b3afadcbe support to make N outline entries from 1 cell, https://github.com/microsoft/vscode/issues/115200 85588252af1 notebook - make outline entries use the heading text has preview text b139c10f9a8 add tests for notebook outline de020f04d13 debt - make withTestNotebook easier to use a04913af757 Merge pull request #117716 from microsoft/tyriar/115396 d5eeb40b557 better focus for select boxes in action bars a2bacaf9fc3 Reverting the top margin to avoid a regression e4e9d1f43b2 Fix grammar 1c4daf4886c Merge pull request #117842 from TranquilMarmot/main 6a864f0b679 Add line height for title ba83910eb76 Remove duplicate tooltip 8baa0ebc750 Fixes title casing 36b0a209a51 backups - consolidate web and desktop strategy for backups when auto save is on b44cc868901 Revisit loose primary group check , use string instead of isPrimaryCheck 12675b4797e missing await 19aee3b6ddf untitled.hint let's go back to the button as the default 6dc076b5c4d debt - tackle an old todo aacafc75b37 debt - use CompletionItem#textLabel in more places f5153bbdacd use CompletionItem#textLabel 3c62a8f898b tabs - track last tab in row for wrapping de50318b48f text files - open an editor that fails to auto save (#115840) b497d17fec9 View: Maximize editor group" doesnt work with dragged file between editors (fix #117686) 3aff1320b81 my work for march b99df4f2b6e don't pass model service to applyEdit but check model version for edit that come from extensions, fixes https://github.com/microsoft/vscode/issues/117683 8fd4a68845f Factor in workspace trust when switching versions (#117774) f84aa806e45 🆙 distro 23dca79e8e9 🆙 nsfwatcher (#117871) 0a7ea106e6e Merge remote-tracking branch 'bpasero/ben/march-debt' f3ec084d542 Update seti-ui icon theme b061ac534cb Fix #117833 f3f4eebecbd Label custom editor as deleted if the backing file is deleted 64db4d5a1a5 Fixes #117354 d89e2e17a5d Allow single line comment after `{` for auto indent 5766526b0b3 Port the desktop iframe webivew focus improvements to the web 8572664c6c7 Enable semantic features (such as error reporting) in JS/TS notebook cells a74ebb17cfe Add helper for tracking active js/ts editor 1f567e10f37 Fixing two more cases for promises in conditionals 3feb2ece1ed Pick up latest TS version for building VS Code 5c7c41fc3d2 Merge pull request #117723 from microsoft/rebornix/reduce-markdown-flickering 91d73da5e42 Only show `infer return type` refactoring when refactorings are requested d596c568451 fix altClickMovesCursor setting description -> markdownDescription (#117793) a4187782439 Merge remote-tracking branch 'origin/main' into tyriar/remove_flow_control d0a46a03279 Merge pull request #117734 from jeanp413/fix-117682 ba9c72b1ff7 Merge pull request #117762 from microsoft/tyriar/remove_ext_host_proc cadb56785ab Merge branch 'main' into tyriar/remove_ext_host_proc e0b4ebc148d Merge remote-tracking branch 'origin/main' into tyriar/remove_flow_control f4c1da9ca64 Update distro ce4bbc7a19e bump version to 1.55 abdf5767046 ipc - allow to configure proxy c41922bf427 chore - cleanup registerSingleton service usages 91a246998c2 Remove flow control setting bd272ea6b74 chore - have a single display change listener 1f0f03e4a03 ipc - adopt utility methods (#114418) df5d7c257df Remove exthost terminal processes 5f234672f57 fix: only use the readonly attribute on the IOS 509cd79dbd6 text file model - drop custom touch method and just go through normal save code 437904db063 file service - add a atomic read option 45f5c4d43f0 Fixes #117682 3d988a6800f Remove focus handling on the xterm element 9a9551b89fc pfs - copy should preserve dangling symbolic links 1e799f5a17e anything quick pick - only restore editor view state in certain cases acea3970993 workspaces - use recursive mkdirSync a469f5eafaa storage - rename storageservice2 => storageservice 2ab5a60c0b8 storage - drop old node based storage service 5fabc0d9dc1 smoke test - remove code only needed for stable january release f5d9bdc8466 fix microsoft/vscode#117095 de-duplicate location results 4cda94b60c1 Remove escaping whitespace characters 495c0e996ad fix cursor position when at the start of RTL syntax tokens 234c7a45fee refactor change to fix fault and reduce diff bf426c250ec structure FilterOptions.textFilter to hold negate flag 03ad36a18b6 Fix negation logic for filterResourceMarkers and filterRelatedInformation 878b0087e06 simplify negate logic in filterMarker 5a6c46fe60a fix #62531 support negation in text filter of Problems 490d7e38da9 Merge branch 'master' into fix-95671 057a47c1b62 Merge branch 'master' into fix-95671 8b73103dedf Merge branch 'master' of https://github.com/matthew-haines/vscode ac89d9ef71f Fixed logic for setCollapseStateForRest and alt-click in editor 9e1b929816d Fixed logic for setCollapseStateForRest 330f6052ebb Added actions for folding/unfolding all regions except selected 8ef113d399c Added collapse surrounding regions with alt-click 3374969a2cb Fixes #95671 REVERT: fd6f3bce670 chore: bump electron@11.3.0 (#118680) REVERT: 305bf142199 Remove icon from input row in ports view (#118649) REVERT: b5af426d34c Properly dispose everything in tunnel view cells (#118546) REVERT: f299ec03c2a Fix extra port icon (#118529) REVERT: 62dbffbfe91 Merge pull request #118177 from microsoft/joh/bump-version REVERT: 062c67a3210 Merge pull request #118491 from microsoft/env-var-recovery REVERT: e11b6a730c9 Fix #117903 (#118492) REVERT: e7936a3e885 prevent env var relaunch from extension owned terminals REVERT: 3be37a725d6 Merge pull request #118438 from microsoft/tyriar/1_54_117990 REVERT: d461d2fd311 Merge pull request #118265 from microsoft/connor4312/candidate/js-debug-1.54.5 REVERT: 88b4d3f9a4e Merge pull request #118448 from microsoft/tyriar/1_54_118321 REVERT: c48a57b6988 Merge pull request #118437 from microsoft/tyriar/1_54_117956 REVERT: d68ab8fc717 Don't force create a terminal on no reconnect REVERT: f9e6b352d1c Recover on pty host reconnect REVERT: b31f6e1afea Don't force kill ptys on Windows on window exit REVERT: bd655647d79 fixes #118214 (#118425) REVERT: 3a6b7f7cbdc editors - fix mergeAllGroups (#118268) (#118406) REVERT: 06c5e24837e FileSystemProvider extension: throwing a FileSystemError in readFile does not report to user (#118173) REVERT: 61feeef2289 Renaming a folder adds it to history (fix #118080) (#118174) REVERT: dd74fb1d885 debug: update js-debug REVERT: 362f7e441ff Pick up TS 4.2.3 (#118261) REVERT: 6b7199812b4 Don't assume uncompleted category exists (#118250) REVERT: 21ea885f455 Merge pull request #118167 from microsoft/connor4312/candidate/js-debug-1.54.4 REVERT: de16aa4bae0 bump version to future 1.54.2 REVERT: 87ff6fb52f1 debug: update js-debug REVERT: f30a9b73e8f bump version (#118144) REVERT: a25525922cd update distro (#118129) REVERT: 42e27fe5cdc Merge pull request #117982 from microsoft/roblou/settingsOpenEditor REVERT: ac575425edc Ensure EditorOptions subclass is passed to openEditor Fix #117952 REVERT: 911868fa126 refs #117960 (#117976) REVERT: 62c69b32bf7 Merge pull request #117972 from microsoft/tyriar/r_1_54_remote_reconnect REVERT: 564f3917935 Fix remote terminal reconnect REVERT: e7989863202 fixes #117924 (#117925) REVERT: c4d7a739c9b Terminal cannot input (#117915) REVERT: 5266d3cc7f3 Merge pull request #117898 from microsoft/tyriar/r1_54_remote_reconnect REVERT: 6f0e457db3f Fix emmet update extensions path issue (#117797) REVERT: 66c7b551727 Implement shouldPersist for all terminals processes REVERT: ae03e39735b Only show `infer return type` refactoring when refactorings are requested (#117800) git-subtree-dir: lib/vscode git-subtree-split: ead2c2ab0f5c93b11e223fd8f4493939be2ee0de
This commit is contained in:
6
src/bootstrap-fork.js
vendored
6
src/bootstrap-fork.js
vendored
@@ -49,7 +49,11 @@ require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']);
|
||||
function pipeLoggingToParent() {
|
||||
const MAX_LENGTH = 100000;
|
||||
|
||||
// Prevent circular stringify and convert arguments to real array
|
||||
/**
|
||||
* Prevent circular stringify and convert arguments to real array
|
||||
*
|
||||
* @param {IArguments} args
|
||||
*/
|
||||
function safeToArray(args) {
|
||||
const seen = [];
|
||||
const argsArray = [];
|
||||
|
||||
36
src/bootstrap-node.js
vendored
36
src/bootstrap-node.js
vendored
@@ -6,6 +6,42 @@
|
||||
//@ts-check
|
||||
'use strict';
|
||||
|
||||
// Setup current working directory in all our node & electron processes
|
||||
// - Windows: call `process.chdir()` to always set application folder as cwd
|
||||
// - Posix: allow to change the current working dir via `VSCODE_CWD` if defined
|
||||
// - all OS: store the `process.cwd()` inside `VSCODE_CWD` for consistent lookups
|
||||
// TODO@bpasero revisit if chdir() on Windows is needed in the future still
|
||||
function setupCurrentWorkingDirectory() {
|
||||
const path = require('path');
|
||||
|
||||
try {
|
||||
let cwd = process.env['VSCODE_CWD'];
|
||||
|
||||
// remember current working directory in environment
|
||||
// unless it was given to us already from outside
|
||||
if (typeof cwd !== 'string') {
|
||||
cwd = process.cwd();
|
||||
process.env['VSCODE_CWD'] = cwd;
|
||||
}
|
||||
|
||||
// Windows: always set application folder as current working dir
|
||||
if (process.platform === 'win32') {
|
||||
process.chdir(path.dirname(process.execPath));
|
||||
}
|
||||
|
||||
// Linux/macOS: allow to change current working dir based on env
|
||||
else {
|
||||
if (cwd !== process.cwd()) {
|
||||
process.chdir(cwd);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
setupCurrentWorkingDirectory();
|
||||
|
||||
/**
|
||||
* Add support for redirecting the loading of node modules
|
||||
*
|
||||
|
||||
11
src/bootstrap-window.js
vendored
11
src/bootstrap-window.js
vendored
@@ -23,11 +23,10 @@
|
||||
}(this, function () {
|
||||
const bootstrapLib = bootstrap();
|
||||
const preloadGlobals = globals();
|
||||
const sandbox = preloadGlobals.context.sandbox;
|
||||
const webFrame = preloadGlobals.webFrame;
|
||||
const safeProcess = preloadGlobals.process;
|
||||
const configuration = parseWindowConfiguration();
|
||||
const useCustomProtocol = sandbox || typeof safeProcess.env['ENABLE_VSCODE_BROWSER_CODE_LOADING'] === 'string';
|
||||
const useCustomProtocol = safeProcess.sandboxed || typeof safeProcess.env['ENABLE_VSCODE_BROWSER_CODE_LOADING'] === 'string';
|
||||
|
||||
// Start to resolve process.env before anything gets load
|
||||
// so that we can run loading and resolving in parallel
|
||||
@@ -83,7 +82,7 @@
|
||||
}
|
||||
|
||||
// replace the patched electron fs with the original node fs for all AMD code (TODO@sandbox non-sandboxed only)
|
||||
if (!sandbox) {
|
||||
if (!safeProcess.sandboxed) {
|
||||
require.define('fs', [], function () { return require.__$__nodeRequire('original-fs'); });
|
||||
}
|
||||
|
||||
@@ -115,7 +114,7 @@
|
||||
// - sandbox: we list paths of webpacked modules to help the loader
|
||||
// - non-sandbox: we signal that any module that does not begin with
|
||||
// `vs/` should be loaded using node.js require()
|
||||
if (sandbox) {
|
||||
if (safeProcess.sandboxed) {
|
||||
loaderConfig.paths = {
|
||||
'vscode-textmate': `../node_modules/vscode-textmate/release/main`,
|
||||
'vscode-oniguruma': `../node_modules/vscode-oniguruma/release/main`,
|
||||
@@ -159,7 +158,9 @@
|
||||
|
||||
// Wait for process environment being fully resolved
|
||||
performance.mark('code/willWaitForShellEnv');
|
||||
await whenEnvResolved;
|
||||
if (!safeProcess.env['VSCODE_SKIP_PROCESS_ENV_PATCHING'] /* TODO@bpasero for https://github.com/microsoft/vscode/issues/108804 */) {
|
||||
await whenEnvResolved;
|
||||
}
|
||||
performance.mark('code/didWaitForShellEnv');
|
||||
|
||||
// Callback only after process environment is resolved
|
||||
|
||||
2
src/bootstrap.js
vendored
2
src/bootstrap.js
vendored
@@ -180,7 +180,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {import('./vs/base/parts/sandbox/electron-sandbox/globals').IPartialNodeProcess | NodeJS.Process}
|
||||
* @returns {import('./vs/base/parts/sandbox/electron-sandbox/globals').ISandboxNodeProcess | NodeJS.Process}
|
||||
*/
|
||||
function safeProcess() {
|
||||
if (typeof process !== 'undefined') {
|
||||
|
||||
48
src/main.js
48
src/main.js
@@ -15,7 +15,7 @@ const os = require('os');
|
||||
const { getNLSConfiguration } = require('./vs/base/node/languagePacks');
|
||||
const bootstrap = require('./bootstrap');
|
||||
const bootstrapNode = require('./bootstrap-node');
|
||||
const { getDefaultUserDataPath } = require('./vs/base/node/userDataPath');
|
||||
const { getUserDataPath } = require('./vs/platform/environment/node/userDataPath');
|
||||
/** @type {Partial<import('./vs/platform/product/common/productService').IProductConfiguration>} */
|
||||
const product = require('../product.json');
|
||||
const { app, protocol, crashReporter } = require('electron');
|
||||
@@ -49,9 +49,6 @@ if (portable && portable.isPortable) {
|
||||
app.setAppLogsPath(path.join(userDataPath, 'logs'));
|
||||
}
|
||||
|
||||
// Update cwd based on environment and platform
|
||||
setCurrentWorkingDirectory();
|
||||
|
||||
// Register custom schemes with privileges
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{
|
||||
@@ -161,9 +158,12 @@ function configureCommandlineSwitchesSync(cliArgs) {
|
||||
// Persistently enable proposed api via argv.json: https://github.com/microsoft/vscode/issues/99775
|
||||
'enable-proposed-api',
|
||||
|
||||
// TODO@bpasero remove me once testing is done on `vscode-file` protocol
|
||||
// TODO@sandbox remove me once testing is done on `vscode-file` protocol
|
||||
// (all traces of `enable-browser-code-loading` and `ENABLE_VSCODE_BROWSER_CODE_LOADING`)
|
||||
'enable-browser-code-loading'
|
||||
'enable-browser-code-loading',
|
||||
|
||||
// Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.
|
||||
'log-level',
|
||||
];
|
||||
|
||||
// Read argv config
|
||||
@@ -208,6 +208,12 @@ function configureCommandlineSwitchesSync(cliArgs) {
|
||||
process.env['ENABLE_VSCODE_BROWSER_CODE_LOADING'] = argvValue;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'log-level':
|
||||
if (typeof argvValue === 'string') {
|
||||
process.argv.push('--log', argvValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -424,19 +430,6 @@ function getJSFlags(cliArgs) {
|
||||
return jsFlags.length > 0 ? jsFlags.join(' ') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./vs/platform/environment/common/argv').NativeParsedArgs} cliArgs
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function getUserDataPath(cliArgs) {
|
||||
if (portable.isPortable) {
|
||||
return path.join(portable.portableDataPath, 'user-data');
|
||||
}
|
||||
|
||||
return path.resolve(cliArgs['user-data-dir'] || getDefaultUserDataPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {import('./vs/platform/environment/common/argv').NativeParsedArgs}
|
||||
*/
|
||||
@@ -454,19 +447,6 @@ function parseCLIArgs() {
|
||||
});
|
||||
}
|
||||
|
||||
function setCurrentWorkingDirectory() {
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
process.env['VSCODE_CWD'] = process.cwd(); // remember as environment variable
|
||||
process.chdir(path.dirname(app.getPath('exe'))); // always set application folder as cwd
|
||||
} else if (process.env['VSCODE_CWD']) {
|
||||
process.chdir(process.env['VSCODE_CWD']);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
function registerListeners() {
|
||||
|
||||
/**
|
||||
@@ -516,7 +496,7 @@ function getNodeCachedDir() {
|
||||
return new class {
|
||||
|
||||
constructor() {
|
||||
this.value = this._compute();
|
||||
this.value = this.compute();
|
||||
}
|
||||
|
||||
async ensureExists() {
|
||||
@@ -531,7 +511,7 @@ function getNodeCachedDir() {
|
||||
}
|
||||
}
|
||||
|
||||
_compute() {
|
||||
compute() {
|
||||
if (process.argv.indexOf('--no-cached-data') > 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
{
|
||||
"ban-eval-calls": [
|
||||
"vs/workbench/api/worker/extHostExtensionService.ts"
|
||||
"vs/workbench/api/worker/extHostExtensionService.ts",
|
||||
"vs/base/worker/workerMain",
|
||||
"vs/workbench/services/extensions/worker/extensionHostWorkerMain"
|
||||
],
|
||||
"ban-function-calls": [
|
||||
"vs/workbench/api/worker/extHostExtensionService.ts",
|
||||
"vs/base/worker/workerMain",
|
||||
"vs/workbench/services/extensions/worker/extensionHostWorkerMain",
|
||||
"vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts",
|
||||
"vs/workbench/services/keybinding/test/electron-browser/keyboardMapperTestUtils.ts"
|
||||
],
|
||||
|
||||
@@ -383,6 +383,7 @@ export class SelectActionViewItem extends BaseActionViewItem {
|
||||
super(ctx, action);
|
||||
|
||||
this.selectBox = new SelectBox(options, selected, contextViewProvider, undefined, selectBoxOptions);
|
||||
this.selectBox.setFocusable(false);
|
||||
|
||||
this._register(this.selectBox);
|
||||
this.registerListeners();
|
||||
@@ -406,6 +407,10 @@ export class SelectActionViewItem extends BaseActionViewItem {
|
||||
return option;
|
||||
}
|
||||
|
||||
setFocusable(focusable: boolean): void {
|
||||
this.selectBox.setFocusable(focusable);
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.selectBox) {
|
||||
this.selectBox.focus();
|
||||
|
||||
@@ -20,10 +20,6 @@
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.monaco-action-bar.reverse .actions-container {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
|
||||
@@ -28,9 +28,7 @@ export interface IActionViewItemProvider {
|
||||
|
||||
export const enum ActionsOrientation {
|
||||
HORIZONTAL,
|
||||
HORIZONTAL_REVERSE,
|
||||
VERTICAL,
|
||||
VERTICAL_REVERSE,
|
||||
}
|
||||
|
||||
export interface ActionTrigger {
|
||||
@@ -135,21 +133,11 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
previousKeys = [KeyCode.LeftArrow];
|
||||
nextKeys = [KeyCode.RightArrow];
|
||||
break;
|
||||
case ActionsOrientation.HORIZONTAL_REVERSE:
|
||||
previousKeys = [KeyCode.RightArrow];
|
||||
nextKeys = [KeyCode.LeftArrow];
|
||||
this.domNode.className += ' reverse';
|
||||
break;
|
||||
case ActionsOrientation.VERTICAL:
|
||||
previousKeys = [KeyCode.UpArrow];
|
||||
nextKeys = [KeyCode.DownArrow];
|
||||
this.domNode.className += ' vertical';
|
||||
break;
|
||||
case ActionsOrientation.VERTICAL_REVERSE:
|
||||
previousKeys = [KeyCode.DownArrow];
|
||||
nextKeys = [KeyCode.UpArrow];
|
||||
this.domNode.className += ' vertical reverse';
|
||||
break;
|
||||
}
|
||||
|
||||
this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_DOWN, e => {
|
||||
@@ -163,8 +151,12 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
eventHandled = this.focusNext();
|
||||
} else if (event.equals(KeyCode.Escape) && this.cancelHasListener) {
|
||||
this._onDidCancel.fire();
|
||||
} else if (event.equals(KeyCode.Home)) {
|
||||
eventHandled = this.focusFirst();
|
||||
} else if (event.equals(KeyCode.End)) {
|
||||
eventHandled = this.focusLast();
|
||||
} else if (event.equals(KeyCode.Tab) && focusedItem instanceof BaseActionViewItem && focusedItem.trapsArrowNavigation) {
|
||||
this.focusNext();
|
||||
eventHandled = this.focusNext();
|
||||
} else if (this.isTriggerKeyEvent(event)) {
|
||||
// Staying out of the else branch even if not triggered
|
||||
if (this._triggerKeys.keyDown) {
|
||||
@@ -425,9 +417,21 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
}
|
||||
}
|
||||
|
||||
private focusFirst(): boolean {
|
||||
this.focusedItem = this.length() > 1 ? 1 : 0;
|
||||
return this.focusPrevious();
|
||||
}
|
||||
|
||||
private focusLast(): boolean {
|
||||
this.focusedItem = this.length() < 2 ? 0 : this.length() - 2;
|
||||
return this.focusNext();
|
||||
}
|
||||
|
||||
protected focusNext(): boolean {
|
||||
if (typeof this.focusedItem === 'undefined') {
|
||||
this.focusedItem = this.viewItems.length - 1;
|
||||
} else if (this.viewItems.length <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const startIndex = this.focusedItem;
|
||||
@@ -450,6 +454,8 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
protected focusPrevious(): boolean {
|
||||
if (typeof this.focusedItem === 'undefined') {
|
||||
this.focusedItem = 0;
|
||||
} else if (this.viewItems.length <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const startIndex = this.focusedItem;
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.monaco-text-button:focus {
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
|
||||
.monaco-text-button:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -20,4 +20,5 @@ export interface IHoverDelegateOptions {
|
||||
|
||||
export interface IHoverDelegate {
|
||||
showHover(options: IHoverDelegateOptions): IDisposable | undefined;
|
||||
delay: number;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IMatch } from 'vs/base/common/filters';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Range } from 'vs/base/common/range';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { IHoverDelegate, IHoverDelegateOptions, IHoverDelegateTarget } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
|
||||
import { AnchorPosition } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
@@ -218,9 +217,6 @@ export class IconLabel extends Disposable {
|
||||
htmlElement.removeAttribute('title');
|
||||
let tooltip = this.getTooltipForCustom(markdownTooltip);
|
||||
|
||||
// Testing has indicated that on Windows and Linux 500 ms matches the native hovers most closely.
|
||||
// On Mac, the delay is 1500.
|
||||
const hoverDelay = isMacintosh ? 1500 : 500;
|
||||
let hoverOptions: IHoverDelegateOptions | undefined;
|
||||
let mouseX: number | undefined;
|
||||
let isHovering = false;
|
||||
@@ -232,9 +228,12 @@ export class IconLabel extends Disposable {
|
||||
}
|
||||
tokenSource = new CancellationTokenSource();
|
||||
function mouseLeaveOrDown(this: HTMLElement, e: MouseEvent): any {
|
||||
if ((e.type === dom.EventType.MOUSE_DOWN) || (<any>e).fromElement === htmlElement) {
|
||||
const isMouseDown = e.type === dom.EventType.MOUSE_DOWN;
|
||||
if (isMouseDown) {
|
||||
hoverDisposable?.dispose();
|
||||
hoverDisposable = undefined;
|
||||
}
|
||||
if (isMouseDown || (<any>e).fromElement === htmlElement) {
|
||||
isHovering = false;
|
||||
hoverOptions = undefined;
|
||||
tokenSource.dispose(true);
|
||||
@@ -282,7 +281,7 @@ export class IconLabel extends Disposable {
|
||||
|
||||
}
|
||||
mouseMoveDisposable.dispose();
|
||||
}, hoverDelay);
|
||||
}, hoverDelegate.delay);
|
||||
}
|
||||
const mouseOverDisposable = this._register(domEvent(htmlElement, dom.EventType.MOUSE_OVER, true)(mouseOver.bind(htmlElement)));
|
||||
this.customHovers.set(htmlElement, mouseOverDisposable);
|
||||
|
||||
@@ -27,6 +27,7 @@ const $ = dom.$;
|
||||
|
||||
export interface IInputOptions extends IInputBoxStyles {
|
||||
readonly placeholder?: string;
|
||||
readonly tooltip?: string;
|
||||
readonly ariaLabel?: string;
|
||||
readonly type?: string;
|
||||
readonly validationOptions?: IInputValidationOptions;
|
||||
@@ -95,6 +96,7 @@ export class InputBox extends Widget {
|
||||
private options: IInputOptions;
|
||||
private message: IMessage | null;
|
||||
private placeholder: string;
|
||||
private tooltip: string;
|
||||
private ariaLabel: string;
|
||||
private validation?: IInputValidator;
|
||||
private state: 'idle' | 'open' | 'closed' = 'idle';
|
||||
@@ -133,6 +135,7 @@ export class InputBox extends Widget {
|
||||
mixin(this.options, defaultOpts, false);
|
||||
this.message = null;
|
||||
this.placeholder = this.options.placeholder || '';
|
||||
this.tooltip = this.options.tooltip ?? (this.placeholder || '');
|
||||
this.ariaLabel = this.options.ariaLabel || '';
|
||||
|
||||
this.inputBackground = this.options.inputBackground;
|
||||
@@ -207,6 +210,10 @@ export class InputBox extends Widget {
|
||||
this.setPlaceHolder(this.placeholder);
|
||||
}
|
||||
|
||||
if (this.tooltip) {
|
||||
this.setTooltip(this.tooltip);
|
||||
}
|
||||
|
||||
this.oninput(this.input, () => this.onValueChange());
|
||||
this.onblur(this.input, () => this.onBlur());
|
||||
this.onfocus(this.input, () => this.onFocus());
|
||||
@@ -235,7 +242,11 @@ export class InputBox extends Widget {
|
||||
public setPlaceHolder(placeHolder: string): void {
|
||||
this.placeholder = placeHolder;
|
||||
this.input.setAttribute('placeholder', placeHolder);
|
||||
this.input.title = placeHolder;
|
||||
}
|
||||
|
||||
public setTooltip(tooltip: string): void {
|
||||
this.tooltip = tooltip;
|
||||
this.input.title = tooltip;
|
||||
}
|
||||
|
||||
public setAriaLabel(label: string): void {
|
||||
|
||||
@@ -226,6 +226,14 @@ export class PagedList<T> implements IThemable, IDisposable {
|
||||
this.list.scrollLeft = scrollLeft;
|
||||
}
|
||||
|
||||
setAnchor(index: number | undefined): void {
|
||||
this.list.setAnchor(index);
|
||||
}
|
||||
|
||||
getAnchor(): number | undefined {
|
||||
return this.list.getAnchor();
|
||||
}
|
||||
|
||||
setFocus(indexes: number[]): void {
|
||||
this.list.setFocus(indexes);
|
||||
}
|
||||
@@ -238,12 +246,20 @@ export class PagedList<T> implements IThemable, IDisposable {
|
||||
this.list.focusPrevious(n, loop);
|
||||
}
|
||||
|
||||
focusNextPage(): void {
|
||||
this.list.focusNextPage();
|
||||
focusNextPage(): Promise<void> {
|
||||
return this.list.focusNextPage();
|
||||
}
|
||||
|
||||
focusPreviousPage(): void {
|
||||
this.list.focusPreviousPage();
|
||||
focusPreviousPage(): Promise<void> {
|
||||
return this.list.focusPreviousPage();
|
||||
}
|
||||
|
||||
focusLast(): void {
|
||||
this.list.focusLast();
|
||||
}
|
||||
|
||||
focusFirst(): void {
|
||||
this.list.focusFirst();
|
||||
}
|
||||
|
||||
getFocus(): number[] {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./list';
|
||||
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isNumber } from 'vs/base/common/types';
|
||||
import { range, binarySearch } from 'vs/base/common/arrays';
|
||||
import { range, binarySearch, firstOrDefault } from 'vs/base/common/arrays';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { Gesture } from 'vs/base/browser/touch';
|
||||
@@ -27,6 +27,7 @@ import { IDragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { alert } from 'vs/base/browser/ui/aria/aria';
|
||||
import { IThemable } from 'vs/base/common/styler';
|
||||
import { createStyleSheet } from 'vs/base/browser/dom';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
|
||||
interface ITraitChangeEvent {
|
||||
indexes: number[];
|
||||
@@ -617,27 +618,25 @@ export class MouseController<T> implements IDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
let reference = this.list.getFocus()[0];
|
||||
const selection = this.list.getSelection();
|
||||
reference = reference === undefined ? selection[0] : reference;
|
||||
|
||||
const focus = e.index;
|
||||
|
||||
if (typeof focus === 'undefined') {
|
||||
this.list.setFocus([], e.browserEvent);
|
||||
this.list.setSelection([], e.browserEvent);
|
||||
this.list.setAnchor(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.multipleSelectionSupport && this.isSelectionRangeChangeEvent(e)) {
|
||||
return this.changeSelection(e, reference);
|
||||
return this.changeSelection(e);
|
||||
}
|
||||
|
||||
if (this.multipleSelectionSupport && this.isSelectionChangeEvent(e)) {
|
||||
return this.changeSelection(e, reference);
|
||||
return this.changeSelection(e);
|
||||
}
|
||||
|
||||
this.list.setFocus([focus], e.browserEvent);
|
||||
this.list.setAnchor(focus);
|
||||
|
||||
if (!isMouseRightClick(e.browserEvent)) {
|
||||
this.list.setSelection([focus], e.browserEvent);
|
||||
@@ -659,15 +658,16 @@ export class MouseController<T> implements IDisposable {
|
||||
this.list.setSelection(focus, e.browserEvent);
|
||||
}
|
||||
|
||||
private changeSelection(e: IListMouseEvent<T> | IListTouchEvent<T>, reference: number | undefined): void {
|
||||
private changeSelection(e: IListMouseEvent<T> | IListTouchEvent<T>): void {
|
||||
const focus = e.index!;
|
||||
const anchor = this.list.getAnchor();
|
||||
|
||||
if (this.isSelectionRangeChangeEvent(e) && reference !== undefined) {
|
||||
const min = Math.min(reference, focus);
|
||||
const max = Math.max(reference, focus);
|
||||
if (this.isSelectionRangeChangeEvent(e) && typeof anchor === 'number') {
|
||||
const min = Math.min(anchor, focus);
|
||||
const max = Math.max(anchor, focus);
|
||||
const rangeSelection = range(min, max + 1);
|
||||
const selection = this.list.getSelection();
|
||||
const contiguousRange = getContiguousRangeContaining(disjunction(selection, [reference]), reference);
|
||||
const contiguousRange = getContiguousRangeContaining(disjunction(selection, [anchor]), anchor);
|
||||
|
||||
if (contiguousRange.length === 0) {
|
||||
return;
|
||||
@@ -675,12 +675,14 @@ export class MouseController<T> implements IDisposable {
|
||||
|
||||
const newSelection = disjunction(rangeSelection, relativeComplement(selection, contiguousRange));
|
||||
this.list.setSelection(newSelection, e.browserEvent);
|
||||
this.list.setFocus([focus], e.browserEvent);
|
||||
|
||||
} else if (this.isSelectionSingleChangeEvent(e)) {
|
||||
const selection = this.list.getSelection();
|
||||
const newSelection = selection.filter(i => i !== focus);
|
||||
|
||||
this.list.setFocus([focus]);
|
||||
this.list.setAnchor(focus);
|
||||
|
||||
if (selection.length === newSelection.length) {
|
||||
this.list.setSelection([...newSelection, focus], e.browserEvent);
|
||||
@@ -1130,8 +1132,9 @@ export interface IListOptionsUpdate extends IListViewOptionsUpdate {
|
||||
|
||||
export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
|
||||
private focus: Trait<T>;
|
||||
private focus = new Trait<T>('focused');
|
||||
private selection: Trait<T>;
|
||||
private anchor = new Trait<T>('anchor');
|
||||
private eventBufferer = new EventBufferer();
|
||||
protected view: ListView<T>;
|
||||
private spliceable: ISpliceable<T>;
|
||||
@@ -1223,7 +1226,6 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
) {
|
||||
const role = this._options.accessibilityProvider && this._options.accessibilityProvider.getWidgetRole ? this._options.accessibilityProvider?.getWidgetRole() : 'list';
|
||||
this.selection = new SelectionTrait(role !== 'listbox');
|
||||
this.focus = new Trait('focused');
|
||||
|
||||
mixin(_options, defaultStyles, false);
|
||||
|
||||
@@ -1259,11 +1261,13 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
this.spliceable = new CombinedSpliceable([
|
||||
new TraitSpliceable(this.focus, this.view, _options.identityProvider),
|
||||
new TraitSpliceable(this.selection, this.view, _options.identityProvider),
|
||||
new TraitSpliceable(this.anchor, this.view, _options.identityProvider),
|
||||
this.view
|
||||
]);
|
||||
|
||||
this.disposables.add(this.focus);
|
||||
this.disposables.add(this.selection);
|
||||
this.disposables.add(this.anchor);
|
||||
this.disposables.add(this.view);
|
||||
this.disposables.add(this._onDidDispose);
|
||||
|
||||
@@ -1436,6 +1440,23 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
return this.getSelection().map(i => this.view.element(i));
|
||||
}
|
||||
|
||||
setAnchor(index: number | undefined): void {
|
||||
if (typeof index === 'undefined') {
|
||||
this.anchor.set([]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 0 || index >= this.length) {
|
||||
throw new ListError(this.user, `Invalid index ${index}`);
|
||||
}
|
||||
|
||||
this.anchor.set([index]);
|
||||
}
|
||||
|
||||
getAnchor(): number | undefined {
|
||||
return firstOrDefault(this.anchor.get(), undefined);
|
||||
}
|
||||
|
||||
setFocus(indexes: number[], browserEvent?: UIEvent): void {
|
||||
for (const index of indexes) {
|
||||
if (index < 0 || index >= this.length) {
|
||||
@@ -1468,7 +1489,7 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
focusNextPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): void {
|
||||
async focusNextPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): Promise<void> {
|
||||
let lastPageIndex = this.view.indexAt(this.view.getScrollTop() + this.view.renderHeight);
|
||||
lastPageIndex = lastPageIndex === 0 ? 0 : lastPageIndex - 1;
|
||||
const lastPageElement = this.view.element(lastPageIndex);
|
||||
@@ -1490,12 +1511,13 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
this.setFocus([]);
|
||||
|
||||
// Let the scroll event listener run
|
||||
setTimeout(() => this.focusNextPage(browserEvent, filter), 0);
|
||||
await timeout(0);
|
||||
await this.focusNextPage(browserEvent, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
focusPreviousPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): void {
|
||||
async focusPreviousPage(browserEvent?: UIEvent, filter?: (element: T) => boolean): Promise<void> {
|
||||
let firstPageIndex: number;
|
||||
const scrollTop = this.view.getScrollTop();
|
||||
|
||||
@@ -1524,7 +1546,8 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
this.setFocus([]);
|
||||
|
||||
// Let the scroll event listener run
|
||||
setTimeout(() => this.focusPreviousPage(browserEvent, filter), 0);
|
||||
await timeout(0);
|
||||
await this.focusPreviousPage(browserEvent, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,3 +85,11 @@
|
||||
.menubar.compact .toolbar-toggle-more::before {
|
||||
content: "\eb94" !important;
|
||||
}
|
||||
|
||||
/* Match behavior of outline for activity bar icons */
|
||||
.menubar.compact > .menubar-menu-button.open,
|
||||
.menubar.compact > .menubar-menu-button:focus,
|
||||
.menubar.compact > .menubar-menu-button:hover {
|
||||
outline-width: 1px !important;
|
||||
outline-offset: -8px !important;
|
||||
}
|
||||
|
||||
@@ -976,7 +976,7 @@ export class MenuBar extends Disposable {
|
||||
menuHolder.style.right = `${this.container.clientWidth}px`;
|
||||
menuHolder.style.left = 'auto';
|
||||
} else {
|
||||
menuHolder.style.top = `${this.container.clientHeight}px`;
|
||||
menuHolder.style.top = `${buttonBoundingRect.bottom}px`;
|
||||
menuHolder.style.left = `${buttonBoundingRect.left}px`;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,27 +85,42 @@
|
||||
}
|
||||
|
||||
.monaco-sash.vertical > .orthogonal-drag-handle.start {
|
||||
left: calc(var(--sash-size) / -2);
|
||||
left: calc(var(--sash-size) * -0.5);
|
||||
top: calc(var(--sash-size) * -1);
|
||||
}
|
||||
.monaco-sash.vertical > .orthogonal-drag-handle.end {
|
||||
left: calc(var(--sash-size) / -2);
|
||||
left: calc(var(--sash-size) * -0.5);
|
||||
bottom: calc(var(--sash-size) * -1);
|
||||
}
|
||||
.monaco-sash.horizontal > .orthogonal-drag-handle.start {
|
||||
top: calc(var(--sash-size) / -2);
|
||||
top: calc(var(--sash-size) * -0.5);
|
||||
left: calc(var(--sash-size) * -1);
|
||||
}
|
||||
.monaco-sash.horizontal > .orthogonal-drag-handle.end {
|
||||
top: calc(var(--sash-size) / -2);
|
||||
top: calc(var(--sash-size) * -0.5);
|
||||
right: calc(var(--sash-size) * -1);
|
||||
}
|
||||
|
||||
.monaco-sash {
|
||||
.monaco-sash:before {
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: background-color 0.1s ease-out;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.monaco-sash.vertical:before {
|
||||
width: var(--sash-hover-size);
|
||||
left: calc(50% - (var(--sash-hover-size) / 2));
|
||||
}
|
||||
|
||||
.monaco-sash.horizontal:before {
|
||||
height: var(--sash-hover-size);
|
||||
top: calc(50% - (var(--sash-hover-size) / 2));
|
||||
}
|
||||
|
||||
/** Debug **/
|
||||
|
||||
.monaco-sash.debug {
|
||||
|
||||
@@ -81,6 +81,13 @@ export function setGlobalSashSize(size: number): void {
|
||||
onDidChangeGlobalSize.fire(size);
|
||||
}
|
||||
|
||||
let globalHoverDelay = 300;
|
||||
const onDidChangeHoverDelay = new Emitter<number>();
|
||||
export function setGlobalHoverDelay(size: number): void {
|
||||
globalHoverDelay = size;
|
||||
onDidChangeHoverDelay.fire(size);
|
||||
}
|
||||
|
||||
export class Sash extends Disposable {
|
||||
|
||||
private el: HTMLElement;
|
||||
@@ -88,7 +95,8 @@ export class Sash extends Disposable {
|
||||
private hidden: boolean;
|
||||
private orientation!: Orientation;
|
||||
private size: number;
|
||||
private hoverDelayer = this._register(new Delayer(300));
|
||||
private hoverDelay = globalHoverDelay;
|
||||
private hoverDelayer = this._register(new Delayer(this.hoverDelay));
|
||||
|
||||
private _state: SashState = SashState.Enabled;
|
||||
get state(): SashState { return this._state; }
|
||||
@@ -221,6 +229,8 @@ export class Sash extends Disposable {
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(onDidChangeHoverDelay.event(delay => this.hoverDelay = delay));
|
||||
|
||||
this.hidden = false;
|
||||
this.layoutProvider = layoutProvider;
|
||||
|
||||
@@ -403,7 +413,7 @@ export class Sash extends Disposable {
|
||||
sash.hoverDelayer.cancel();
|
||||
sash.el.classList.add('hover');
|
||||
} else {
|
||||
sash.hoverDelayer.trigger(() => sash.el.classList.add('hover'));
|
||||
sash.hoverDelayer.trigger(() => sash.el.classList.add('hover'), sash.hoverDelay).then(undefined, () => { });
|
||||
}
|
||||
|
||||
if (!fromLinkedSash && sash.linkedSash) {
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface ISelectBoxDelegate extends IDisposable {
|
||||
setAriaLabel(label: string): void;
|
||||
focus(): void;
|
||||
blur(): void;
|
||||
setFocusable(focus: boolean): void;
|
||||
|
||||
// Delegated Widget interface
|
||||
render(container: HTMLElement): void;
|
||||
@@ -93,41 +94,43 @@ export class SelectBox extends Widget implements ISelectBoxDelegate {
|
||||
|
||||
// Public SelectBox Methods - routed through delegate interface
|
||||
|
||||
public get onDidSelect(): Event<ISelectData> {
|
||||
get onDidSelect(): Event<ISelectData> {
|
||||
return this.selectBoxDelegate.onDidSelect;
|
||||
}
|
||||
|
||||
public setOptions(options: ISelectOptionItem[], selected?: number): void {
|
||||
setOptions(options: ISelectOptionItem[], selected?: number): void {
|
||||
this.selectBoxDelegate.setOptions(options, selected);
|
||||
}
|
||||
|
||||
public select(index: number): void {
|
||||
select(index: number): void {
|
||||
this.selectBoxDelegate.select(index);
|
||||
}
|
||||
|
||||
public setAriaLabel(label: string): void {
|
||||
setAriaLabel(label: string): void {
|
||||
this.selectBoxDelegate.setAriaLabel(label);
|
||||
}
|
||||
|
||||
public focus(): void {
|
||||
focus(): void {
|
||||
this.selectBoxDelegate.focus();
|
||||
}
|
||||
|
||||
public blur(): void {
|
||||
blur(): void {
|
||||
this.selectBoxDelegate.blur();
|
||||
}
|
||||
|
||||
// Public Widget Methods - routed through delegate interface
|
||||
setFocusable(focusable: boolean): void {
|
||||
this.selectBoxDelegate.setFocusable(focusable);
|
||||
}
|
||||
|
||||
public render(container: HTMLElement): void {
|
||||
render(container: HTMLElement): void {
|
||||
this.selectBoxDelegate.render(container);
|
||||
}
|
||||
|
||||
public style(styles: ISelectBoxStyles): void {
|
||||
style(styles: ISelectBoxStyles): void {
|
||||
this.selectBoxDelegate.style(styles);
|
||||
}
|
||||
|
||||
public applyStyles(): void {
|
||||
applyStyles(): void {
|
||||
this.selectBoxDelegate.applyStyles();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,16 +293,22 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
||||
|
||||
public focus(): void {
|
||||
if (this.selectElement) {
|
||||
this.selectElement.tabIndex = 0;
|
||||
this.selectElement.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public blur(): void {
|
||||
if (this.selectElement) {
|
||||
this.selectElement.tabIndex = -1;
|
||||
this.selectElement.blur();
|
||||
}
|
||||
}
|
||||
|
||||
public setFocusable(focusable: boolean): void {
|
||||
this.selectElement.tabIndex = focusable ? 0 : -1;
|
||||
}
|
||||
|
||||
public render(container: HTMLElement): void {
|
||||
this.container = container;
|
||||
container.classList.add('select-container');
|
||||
|
||||
@@ -132,16 +132,22 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate {
|
||||
|
||||
public focus(): void {
|
||||
if (this.selectElement) {
|
||||
this.selectElement.tabIndex = 0;
|
||||
this.selectElement.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public blur(): void {
|
||||
if (this.selectElement) {
|
||||
this.selectElement.tabIndex = -1;
|
||||
this.selectElement.blur();
|
||||
}
|
||||
}
|
||||
|
||||
public setFocusable(focusable: boolean): void {
|
||||
this.selectElement.tabIndex = focusable ? 0 : -1;
|
||||
}
|
||||
|
||||
public render(container: HTMLElement): void {
|
||||
container.classList.add('select-container');
|
||||
container.appendChild(this.selectElement);
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: inherit;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.monaco-pane-view .pane > .pane-header .monaco-action-bar .action-item.select-container {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
.monaco-table-tr {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-table-th {
|
||||
@@ -35,18 +36,12 @@
|
||||
.monaco-table-th,
|
||||
.monaco-table-td {
|
||||
box-sizing: border-box;
|
||||
padding-left: 10px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.monaco-table-th[data-col-index="0"],
|
||||
.monaco-table-td[data-col-index="0"] {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.monaco-table > .monaco-split-view2 .monaco-sash.vertical::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
|
||||
@@ -250,7 +250,10 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
|
||||
|
||||
this.cachedHeight = height;
|
||||
this.splitview.layout(width);
|
||||
this.list.layout(height - this.virtualDelegate.headerRowHeight, width);
|
||||
|
||||
const listHeight = height - this.virtualDelegate.headerRowHeight;
|
||||
this.list.getHTMLElement().style.height = `${listHeight}px`;
|
||||
this.list.layout(listHeight, width);
|
||||
}
|
||||
|
||||
toggleKeyboardNavigation(): void {
|
||||
@@ -273,6 +276,14 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
|
||||
this.list.domFocus();
|
||||
}
|
||||
|
||||
setAnchor(index: number | undefined): void {
|
||||
this.list.setAnchor(index);
|
||||
}
|
||||
|
||||
getAnchor(): number | undefined {
|
||||
return this.list.getAnchor();
|
||||
}
|
||||
|
||||
getSelectedElements(): TRow[] {
|
||||
return this.list.getSelectedElements();
|
||||
}
|
||||
@@ -297,12 +308,12 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
|
||||
this.list.focusPrevious(n, loop, browserEvent);
|
||||
}
|
||||
|
||||
focusNextPage(browserEvent?: UIEvent): void {
|
||||
this.list.focusNextPage(browserEvent);
|
||||
focusNextPage(browserEvent?: UIEvent): Promise<void> {
|
||||
return this.list.focusNextPage(browserEvent);
|
||||
}
|
||||
|
||||
focusPreviousPage(browserEvent?: UIEvent): void {
|
||||
this.list.focusPreviousPage(browserEvent);
|
||||
focusPreviousPage(browserEvent?: UIEvent): Promise<void> {
|
||||
return this.list.focusPreviousPage(browserEvent);
|
||||
}
|
||||
|
||||
focusFirst(browserEvent?: UIEvent): void {
|
||||
@@ -317,6 +328,10 @@ export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
|
||||
return this.list.getFocus();
|
||||
}
|
||||
|
||||
getFocusedElements(): TRow[] {
|
||||
return this.list.getFocusedElements();
|
||||
}
|
||||
|
||||
reveal(index: number, relativeTop?: number): void {
|
||||
this.list.reveal(index, relativeTop);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator, ICollapseStateChangeEvent, ITreeDragAndDrop, TreeDragOverBubble, TreeVisibility, TreeFilterResult, ITreeModelSpliceEvent, TreeMouseEventTarget } from 'vs/base/browser/ui/tree/tree';
|
||||
import { ISpliceable } from 'vs/base/common/sequence';
|
||||
import { IDragAndDropData, StaticDND, DragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { range, equals, distinctES6 } from 'vs/base/common/arrays';
|
||||
import { range, equals, distinctES6, firstOrDefault } from 'vs/base/common/arrays';
|
||||
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { fuzzyScore, FuzzyScore } from 'vs/base/common/filters';
|
||||
@@ -683,6 +683,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
if (typeof options.filterOnType !== 'undefined') {
|
||||
this._filterOnType = !!options.filterOnType;
|
||||
this.filterOnTypeDomNode.checked = this._filterOnType;
|
||||
this.updateFilterOnTypeTitleAndIcon();
|
||||
}
|
||||
|
||||
if (typeof options.automaticKeyboardNavigation !== 'undefined') {
|
||||
@@ -1168,6 +1169,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
|
||||
renderers: IListRenderer<any /* TODO@joao */, any>[],
|
||||
private focusTrait: Trait<T>,
|
||||
private selectionTrait: Trait<T>,
|
||||
private anchorTrait: Trait<T>,
|
||||
options: ITreeNodeListOptions<T, TFilterData, TRef>
|
||||
) {
|
||||
super(user, container, virtualDelegate, renderers, options);
|
||||
@@ -1186,6 +1188,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
|
||||
|
||||
const additionalFocus: number[] = [];
|
||||
const additionalSelection: number[] = [];
|
||||
let anchor: number | undefined;
|
||||
|
||||
elements.forEach((node, index) => {
|
||||
if (this.focusTrait.has(node)) {
|
||||
@@ -1195,6 +1198,10 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
|
||||
if (this.selectionTrait.has(node)) {
|
||||
additionalSelection.push(start + index);
|
||||
}
|
||||
|
||||
if (this.anchorTrait.has(node)) {
|
||||
anchor = start + index;
|
||||
}
|
||||
});
|
||||
|
||||
if (additionalFocus.length > 0) {
|
||||
@@ -1204,6 +1211,10 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
|
||||
if (additionalSelection.length > 0) {
|
||||
super.setSelection(distinctES6([...super.getSelection(), ...additionalSelection]));
|
||||
}
|
||||
|
||||
if (typeof anchor === 'number') {
|
||||
super.setAnchor(anchor);
|
||||
}
|
||||
}
|
||||
|
||||
setFocus(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {
|
||||
@@ -1221,6 +1232,18 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
|
||||
this.selectionTrait.set(indexes.map(i => this.element(i)), browserEvent);
|
||||
}
|
||||
}
|
||||
|
||||
setAnchor(index: number | undefined, fromAPI = false): void {
|
||||
super.setAnchor(index);
|
||||
|
||||
if (!fromAPI) {
|
||||
if (typeof index === 'undefined') {
|
||||
this.anchorTrait.set([]);
|
||||
} else {
|
||||
this.anchorTrait.set([this.element(index)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable {
|
||||
@@ -1230,6 +1253,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
protected model: ITreeModel<T, TFilterData, TRef>;
|
||||
private focus: Trait<T>;
|
||||
private selection: Trait<T>;
|
||||
private anchor: Trait<T>;
|
||||
private eventBufferer = new EventBufferer();
|
||||
private typeFilterController?: TypeFilterController<T, TFilterData>;
|
||||
private focusNavigationFilter: ((node: ITreeNode<T, TFilterData>) => boolean) | undefined;
|
||||
@@ -1298,7 +1322,8 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
|
||||
this.focus = new Trait(_options.identityProvider);
|
||||
this.selection = new Trait(_options.identityProvider);
|
||||
this.view = new TreeNodeList(user, container, treeDelegate, this.renderers, this.focus, this.selection, { ...asListOptions(() => this.model, _options), tree: this });
|
||||
this.anchor = new Trait(_options.identityProvider);
|
||||
this.view = new TreeNodeList(user, container, treeDelegate, this.renderers, this.focus, this.selection, this.anchor, { ...asListOptions(() => this.model, _options), tree: this });
|
||||
|
||||
this.model = this.createModel(user, this.view, _options);
|
||||
onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;
|
||||
@@ -1552,6 +1577,25 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
this.model.refilter();
|
||||
}
|
||||
|
||||
setAnchor(element: TRef | undefined): void {
|
||||
if (typeof element === 'undefined') {
|
||||
return this.view.setAnchor(undefined);
|
||||
}
|
||||
|
||||
const node = this.model.getNode(element);
|
||||
this.anchor.set([node]);
|
||||
|
||||
const index = this.model.getListIndex(element);
|
||||
|
||||
if (index > -1) {
|
||||
this.view.setAnchor(index, true);
|
||||
}
|
||||
}
|
||||
|
||||
getAnchor(): T | undefined {
|
||||
return firstOrDefault(this.anchor.get(), undefined);
|
||||
}
|
||||
|
||||
setSelection(elements: TRef[], browserEvent?: UIEvent): void {
|
||||
const nodes = elements.map(e => this.model.getNode(e));
|
||||
this.selection.set(nodes, browserEvent);
|
||||
@@ -1580,12 +1624,12 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
this.view.focusPrevious(n, loop, browserEvent, filter);
|
||||
}
|
||||
|
||||
focusNextPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void {
|
||||
this.view.focusNextPage(browserEvent, filter);
|
||||
focusNextPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): Promise<void> {
|
||||
return this.view.focusNextPage(browserEvent, filter);
|
||||
}
|
||||
|
||||
focusPreviousPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void {
|
||||
this.view.focusPreviousPage(browserEvent, filter);
|
||||
focusPreviousPage(browserEvent?: UIEvent, filter = this.focusNavigationFilter): Promise<void> {
|
||||
return this.view.focusPreviousPage(browserEvent, filter);
|
||||
}
|
||||
|
||||
focusLast(browserEvent?: UIEvent, filter = this.focusNavigationFilter): void {
|
||||
|
||||
@@ -616,7 +616,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
|
||||
return this.tree.isCollapsible(this.getDataNode(element));
|
||||
}
|
||||
|
||||
isCollapsed(element: T): boolean {
|
||||
isCollapsed(element: TInput | T): boolean {
|
||||
return this.tree.isCollapsed(this.getDataNode(element));
|
||||
}
|
||||
|
||||
@@ -628,6 +628,15 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
|
||||
this.tree.refilter();
|
||||
}
|
||||
|
||||
setAnchor(element: T | undefined): void {
|
||||
this.tree.setAnchor(typeof element === 'undefined' ? undefined : this.getDataNode(element));
|
||||
}
|
||||
|
||||
getAnchor(): T | undefined {
|
||||
const node = this.tree.getAnchor();
|
||||
return node?.element as T;
|
||||
}
|
||||
|
||||
setSelection(elements: T[], browserEvent?: UIEvent): void {
|
||||
const nodes = elements.map(e => this.getDataNode(e));
|
||||
this.tree.setSelection(nodes, browserEvent);
|
||||
@@ -651,12 +660,12 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
|
||||
this.tree.focusPrevious(n, loop, browserEvent);
|
||||
}
|
||||
|
||||
focusNextPage(browserEvent?: UIEvent): void {
|
||||
this.tree.focusNextPage(browserEvent);
|
||||
focusNextPage(browserEvent?: UIEvent): Promise<void> {
|
||||
return this.tree.focusNextPage(browserEvent);
|
||||
}
|
||||
|
||||
focusPreviousPage(browserEvent?: UIEvent): void {
|
||||
this.tree.focusPreviousPage(browserEvent);
|
||||
focusPreviousPage(browserEvent?: UIEvent): Promise<void> {
|
||||
return this.tree.focusPreviousPage(browserEvent);
|
||||
}
|
||||
|
||||
focusLast(browserEvent?: UIEvent): void {
|
||||
|
||||
@@ -8,7 +8,6 @@ import { IndexTreeModel, IIndexTreeModelOptions, IList, IIndexTreeModelSpliceOpt
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent, ITreeModelSpliceEvent, TreeError } from 'vs/base/browser/ui/tree/tree';
|
||||
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
|
||||
import { mergeSort } from 'vs/base/common/arrays';
|
||||
|
||||
export type ITreeNodeCallback<T, TFilterData> = (node: ITreeNode<T, TFilterData>) => void;
|
||||
|
||||
@@ -130,7 +129,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
|
||||
|
||||
private preserveCollapseState(elements: Iterable<ITreeElement<T>> = Iterable.empty()): Iterable<ITreeElement<T>> {
|
||||
if (this.sorter) {
|
||||
elements = mergeSort([...elements], this.sorter.compare.bind(this.sorter));
|
||||
elements = [...elements].sort(this.sorter.compare.bind(this.sorter));
|
||||
}
|
||||
|
||||
return Iterable.map(elements, treeElement => {
|
||||
@@ -185,7 +184,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
|
||||
let childrenNodes = [...node.children] as ITreeNode<T, TFilterData>[];
|
||||
|
||||
if (recursive || first) {
|
||||
childrenNodes = mergeSort(childrenNodes, this.sorter!.compare.bind(this.sorter));
|
||||
childrenNodes = childrenNodes.sort(this.sorter!.compare.bind(this.sorter));
|
||||
}
|
||||
|
||||
return Iterable.map<ITreeNode<T | null, TFilterData>, ITreeElement<T>>(childrenNodes, node => ({
|
||||
|
||||
@@ -3,23 +3,6 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { mergeSort } from 'vs/base/common/arrays';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
/**
|
||||
* @deprecated use `FileAccess.asFileUri(relativePath, requireFn).fsPath`
|
||||
*/
|
||||
export function getPathFromAmdModule(requirefn: typeof require, relativePath: string): string {
|
||||
return getUriFromAmdModule(requirefn, relativePath).fsPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `FileAccess.asFileUri()` for node.js contexts or `FileAccess.asBrowserUri` for browser contexts.
|
||||
*/
|
||||
export function getUriFromAmdModule(requirefn: typeof require, relativePath: string): URI {
|
||||
return URI.parse(requirefn.toUrl(relativePath));
|
||||
}
|
||||
|
||||
export abstract class LoaderStats {
|
||||
abstract get amdLoad(): [string, number][];
|
||||
abstract get amdInvoke(): [string, number][];
|
||||
@@ -27,10 +10,7 @@ export abstract class LoaderStats {
|
||||
abstract get nodeEval(): [string, number][];
|
||||
abstract get nodeRequireTotal(): number;
|
||||
|
||||
|
||||
static get(): LoaderStats {
|
||||
|
||||
|
||||
const amdLoadScript = new Map<string, number>();
|
||||
const amdInvokeFactory = new Map<string, number>();
|
||||
const nodeRequire = new Map<string, number>();
|
||||
@@ -60,7 +40,7 @@ export abstract class LoaderStats {
|
||||
map.set(stat.detail, duration + stat.timestamp);
|
||||
}
|
||||
|
||||
const stats = mergeSort(require.getStats().slice(0), (a, b) => a.timestamp - b.timestamp);
|
||||
const stats = require.getStats().slice(0).sort((a, b) => a.timestamp - b.timestamp);
|
||||
|
||||
for (const stat of stats) {
|
||||
switch (stat.type) {
|
||||
|
||||
@@ -121,58 +121,10 @@ export function quickSelect<T>(nth: number, data: T[], compare: Compare<T>): T {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Like `Array#sort` but always stable. Usually runs a little slower `than Array#sort`
|
||||
* so only use this when actually needing stable sort.
|
||||
*/
|
||||
export function mergeSort<T>(data: T[], compare: Compare<T>): T[] {
|
||||
_sort(data, compare, 0, data.length - 1, []);
|
||||
return data;
|
||||
}
|
||||
|
||||
function _merge<T>(a: T[], compare: Compare<T>, lo: number, mid: number, hi: number, aux: T[]): void {
|
||||
let leftIdx = lo, rightIdx = mid + 1;
|
||||
for (let i = lo; i <= hi; i++) {
|
||||
aux[i] = a[i];
|
||||
}
|
||||
for (let i = lo; i <= hi; i++) {
|
||||
if (leftIdx > mid) {
|
||||
// left side consumed
|
||||
a[i] = aux[rightIdx++];
|
||||
} else if (rightIdx > hi) {
|
||||
// right side consumed
|
||||
a[i] = aux[leftIdx++];
|
||||
} else if (compare(aux[rightIdx], aux[leftIdx]) < 0) {
|
||||
// right element is less -> comes first
|
||||
a[i] = aux[rightIdx++];
|
||||
} else {
|
||||
// left element comes first (less or equal)
|
||||
a[i] = aux[leftIdx++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _sort<T>(a: T[], compare: Compare<T>, lo: number, hi: number, aux: T[]) {
|
||||
if (hi <= lo) {
|
||||
return;
|
||||
}
|
||||
const mid = lo + ((hi - lo) / 2) | 0;
|
||||
_sort(a, compare, lo, mid, aux);
|
||||
_sort(a, compare, mid + 1, hi, aux);
|
||||
if (compare(a[mid], a[mid + 1]) <= 0) {
|
||||
// left and right are sorted and if the last-left element is less
|
||||
// or equals than the first-right element there is nothing else
|
||||
// to do
|
||||
return;
|
||||
}
|
||||
_merge(a, compare, lo, mid, hi, aux);
|
||||
}
|
||||
|
||||
|
||||
export function groupBy<T>(data: ReadonlyArray<T>, compare: (a: T, b: T) => number): T[][] {
|
||||
const result: T[][] = [];
|
||||
let currentGroup: T[] | undefined = undefined;
|
||||
for (const element of mergeSort(data.slice(0), compare)) {
|
||||
for (const element of data.slice(0).sort(compare)) {
|
||||
if (!currentGroup || compare(currentGroup[0], element) !== 0) {
|
||||
currentGroup = [element];
|
||||
result.push(currentGroup);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { canceled, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event, Listener } from 'vs/base/common/event';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
import { extUri as defaultExtUri, IExtUri } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
export function isThenable<T>(obj: unknown): obj is Promise<T> {
|
||||
@@ -592,19 +593,21 @@ export class ResourceQueue implements IDisposable {
|
||||
|
||||
private readonly queues = new Map<string, Queue<void>>();
|
||||
|
||||
queueFor(resource: URI): Queue<void> {
|
||||
const key = resource.toString();
|
||||
if (!this.queues.has(key)) {
|
||||
const queue = new Queue<void>();
|
||||
queue.onFinished(() => {
|
||||
queue.dispose();
|
||||
queueFor(resource: URI, extUri: IExtUri = defaultExtUri): Queue<void> {
|
||||
const key = extUri.getComparisonKey(resource);
|
||||
|
||||
let queue = this.queues.get(key);
|
||||
if (!queue) {
|
||||
queue = new Queue<void>();
|
||||
Event.once(queue.onFinished)(() => {
|
||||
queue?.dispose();
|
||||
this.queues.delete(key);
|
||||
});
|
||||
|
||||
this.queues.set(key, queue);
|
||||
}
|
||||
|
||||
return this.queues.get(key)!;
|
||||
return queue;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -548,6 +548,9 @@ export namespace Codicon {
|
||||
export const runBelow = new Codicon('run-below', { fontCharacter: '\\ebbe' });
|
||||
export const notebookTemplate = new Codicon('notebook-template', { fontCharacter: '\\ebbf' });
|
||||
export const debugRerun = new Codicon('debug-rerun', { fontCharacter: '\\ebc0' });
|
||||
export const workspaceTrusted = new Codicon('workspace-trusted', { fontCharacter: '\\ebc1' });
|
||||
export const workspaceUntrusted = new Codicon('workspace-untrusted', { fontCharacter: '\\ebc2' });
|
||||
export const workspaceUnknown = new Codicon('workspace-unknown', { fontCharacter: '\\ebc3' });
|
||||
|
||||
export const dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition);
|
||||
}
|
||||
|
||||
@@ -838,12 +838,8 @@ export class LcsDiff {
|
||||
let modifiedStop = 0;
|
||||
if (i > 0) {
|
||||
const prevChange = changes[i - 1];
|
||||
if (prevChange.originalLength > 0) {
|
||||
originalStop = prevChange.originalStart + prevChange.originalLength;
|
||||
}
|
||||
if (prevChange.modifiedLength > 0) {
|
||||
modifiedStop = prevChange.modifiedStart + prevChange.modifiedLength;
|
||||
}
|
||||
originalStop = prevChange.originalStart + prevChange.originalLength;
|
||||
modifiedStop = prevChange.modifiedStart + prevChange.modifiedLength;
|
||||
}
|
||||
|
||||
const checkOriginal = change.originalLength > 0;
|
||||
@@ -868,7 +864,11 @@ export class LcsDiff {
|
||||
break;
|
||||
}
|
||||
|
||||
const score = this._boundaryScore(originalStart, change.originalLength, modifiedStart, change.modifiedLength);
|
||||
const touchingPreviousChange = (originalStart === originalStop && modifiedStart === modifiedStop);
|
||||
const score = (
|
||||
(touchingPreviousChange ? 5 : 0)
|
||||
+ this._boundaryScore(originalStart, change.originalLength, modifiedStart, change.modifiedLength)
|
||||
);
|
||||
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
@@ -878,6 +878,14 @@ export class LcsDiff {
|
||||
|
||||
change.originalStart -= bestDelta;
|
||||
change.modifiedStart -= bestDelta;
|
||||
|
||||
const mergedChangeArr: Array<DiffChange | null> = [null];
|
||||
if (i > 0 && this.ChangesOverlap(changes[i - 1], changes[i], mergedChangeArr)) {
|
||||
changes[i - 1] = mergedChangeArr[0]!;
|
||||
changes.splice(i, 1);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// There could be multiple longest common substrings.
|
||||
|
||||
@@ -365,28 +365,15 @@ export function matchesFuzzy2(pattern: string, word: string): IMatch[] | null {
|
||||
return score ? createMatches(score) : null;
|
||||
}
|
||||
|
||||
export function anyScore(pattern: string, lowPattern: string, _patternPos: number, word: string, lowWord: string, _wordPos: number): FuzzyScore {
|
||||
const result = fuzzyScore(pattern, lowPattern, 0, word, lowWord, 0, true);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
let matches: number[] = [];
|
||||
let score = 0;
|
||||
let idx = _wordPos;
|
||||
for (let patternPos = 0; patternPos < lowPattern.length && patternPos < _maxLen; ++patternPos) {
|
||||
const wordPos = lowWord.indexOf(lowPattern.charAt(patternPos), idx);
|
||||
if (wordPos >= 0) {
|
||||
score += 1;
|
||||
matches.unshift(wordPos);
|
||||
idx = wordPos + 1;
|
||||
} else if (matches.length > 0) {
|
||||
// once we have started matching things
|
||||
// we need to match the remaining pattern
|
||||
// characters
|
||||
break;
|
||||
export function anyScore(pattern: string, lowPattern: string, patternPos: number, word: string, lowWord: string, wordPos: number): FuzzyScore {
|
||||
const max = Math.min(13, pattern.length);
|
||||
for (; patternPos < max; patternPos++) {
|
||||
const result = fuzzyScore(pattern, lowPattern, patternPos, word, lowWord, wordPos, false);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return [score, _wordPos, ...matches];
|
||||
return [0, wordPos];
|
||||
}
|
||||
|
||||
//#region --- fuzzyScore ---
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { ParseError, Node, JSONPath, Segment, parseTree, findNodeAtLocation } from './json';
|
||||
import { Edit, format, isEOL, FormattingOptions } from './jsonFormatter';
|
||||
import { mergeSort } from 'vs/base/common/arrays';
|
||||
|
||||
|
||||
export function removeProperty(text: string, path: JSONPath, formattingOptions: FormattingOptions): Edit[] {
|
||||
@@ -156,7 +155,7 @@ export function applyEdit(text: string, edit: Edit): string {
|
||||
}
|
||||
|
||||
export function applyEdits(text: string, edits: Edit[]): string {
|
||||
let sortedEdits = mergeSort(edits, (a, b) => {
|
||||
let sortedEdits = edits.slice(0).sort((a, b) => {
|
||||
const diff = a.offset - b.offset;
|
||||
if (diff === 0) {
|
||||
return a.length - b.length;
|
||||
|
||||
@@ -7,113 +7,117 @@
|
||||
|
||||
//@ts-check
|
||||
|
||||
/**
|
||||
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
|
||||
*/
|
||||
function _definePolyfillMarks(timeOrigin) {
|
||||
(function () {
|
||||
|
||||
const _data = [];
|
||||
if (typeof timeOrigin === 'number') {
|
||||
_data.push('code/timeOrigin', timeOrigin);
|
||||
}
|
||||
/**
|
||||
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
|
||||
*/
|
||||
function _definePolyfillMarks(timeOrigin) {
|
||||
|
||||
function mark(name) {
|
||||
_data.push(name, Date.now());
|
||||
}
|
||||
function getMarks() {
|
||||
const result = [];
|
||||
for (let i = 0; i < _data.length; i += 2) {
|
||||
result.push({
|
||||
name: _data[i],
|
||||
startTime: _data[i + 1],
|
||||
});
|
||||
const _data = [];
|
||||
if (typeof timeOrigin === 'number') {
|
||||
_data.push('code/timeOrigin', timeOrigin);
|
||||
}
|
||||
return result;
|
||||
|
||||
function mark(name) {
|
||||
_data.push(name, Date.now());
|
||||
}
|
||||
function getMarks() {
|
||||
const result = [];
|
||||
for (let i = 0; i < _data.length; i += 2) {
|
||||
result.push({
|
||||
name: _data[i],
|
||||
startTime: _data[i + 1],
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return { mark, getMarks };
|
||||
}
|
||||
return { mark, getMarks };
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
|
||||
*/
|
||||
function _define() {
|
||||
/**
|
||||
* @returns {{mark(name:string):void, getMarks():{name:string, startTime:number}[]}}
|
||||
*/
|
||||
function _define() {
|
||||
|
||||
if (typeof performance === 'object' && typeof performance.mark === 'function') {
|
||||
// in a browser context, reuse performance-util
|
||||
if (typeof performance === 'object' && typeof performance.mark === 'function') {
|
||||
// in a browser context, reuse performance-util
|
||||
|
||||
if (typeof performance.timeOrigin !== 'number' && !performance.timing) {
|
||||
// safari & webworker: because there is no timeOrigin and no workaround
|
||||
// we use the `Date.now`-based polyfill.
|
||||
return _definePolyfillMarks();
|
||||
if (typeof performance.timeOrigin !== 'number' && !performance.timing) {
|
||||
// safari & webworker: because there is no timeOrigin and no workaround
|
||||
// we use the `Date.now`-based polyfill.
|
||||
return _definePolyfillMarks();
|
||||
|
||||
} else {
|
||||
// use "native" performance for mark and getMarks
|
||||
return {
|
||||
mark(name) {
|
||||
performance.mark(name);
|
||||
},
|
||||
getMarks() {
|
||||
let timeOrigin = performance.timeOrigin;
|
||||
if (typeof timeOrigin !== 'number') {
|
||||
// safari: there is no timerOrigin but in renderers there is the timing-property
|
||||
// see https://bugs.webkit.org/show_bug.cgi?id=174862
|
||||
timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart;
|
||||
}
|
||||
const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }];
|
||||
for (const entry of performance.getEntriesByType('mark')) {
|
||||
result.push({
|
||||
name: entry.name,
|
||||
startTime: Math.round(timeOrigin + entry.startTime)
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} else if (typeof process === 'object') {
|
||||
// node.js: use the normal polyfill but add the timeOrigin
|
||||
// from the node perf_hooks API as very first mark
|
||||
const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin);
|
||||
return _definePolyfillMarks(timeOrigin);
|
||||
|
||||
} else {
|
||||
// use "native" performance for mark and getMarks
|
||||
return {
|
||||
mark(name) {
|
||||
performance.mark(name);
|
||||
},
|
||||
getMarks() {
|
||||
let timeOrigin = performance.timeOrigin;
|
||||
if (typeof timeOrigin !== 'number') {
|
||||
// safari: there is no timerOrigin but in renderers there is the timing-property
|
||||
// see https://bugs.webkit.org/show_bug.cgi?id=174862
|
||||
timeOrigin = performance.timing.navigationStart || performance.timing.redirectStart || performance.timing.fetchStart;
|
||||
}
|
||||
const result = [{ name: 'code/timeOrigin', startTime: Math.round(timeOrigin) }];
|
||||
for (const entry of performance.getEntriesByType('mark')) {
|
||||
result.push({
|
||||
name: entry.name,
|
||||
startTime: Math.round(timeOrigin + entry.startTime)
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
// unknown environment
|
||||
console.trace('perf-util loaded in UNKNOWN environment');
|
||||
return _definePolyfillMarks();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (typeof process === 'object') {
|
||||
// node.js: use the normal polyfill but add the timeOrigin
|
||||
// from the node perf_hooks API as very first mark
|
||||
const timeOrigin = Math.round((require.nodeRequire || require)('perf_hooks').performance.timeOrigin);
|
||||
return _definePolyfillMarks(timeOrigin);
|
||||
function _factory(sharedObj) {
|
||||
if (!sharedObj.MonacoPerformanceMarks) {
|
||||
sharedObj.MonacoPerformanceMarks = _define();
|
||||
}
|
||||
return sharedObj.MonacoPerformanceMarks;
|
||||
}
|
||||
|
||||
// This module can be loaded in an amd and commonjs-context.
|
||||
// Because we want both instances to use the same perf-data
|
||||
// we store them globally
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var sharedObj;
|
||||
if (typeof global === 'object') {
|
||||
// nodejs
|
||||
sharedObj = global;
|
||||
} else if (typeof self === 'object') {
|
||||
// browser
|
||||
sharedObj = self;
|
||||
} else {
|
||||
// unknown environment
|
||||
console.trace('perf-util loaded in UNKNOWN environment');
|
||||
return _definePolyfillMarks();
|
||||
sharedObj = {};
|
||||
}
|
||||
}
|
||||
|
||||
function _factory(sharedObj) {
|
||||
if (!sharedObj.MonacoPerformanceMarks) {
|
||||
sharedObj.MonacoPerformanceMarks = _define();
|
||||
if (typeof define === 'function') {
|
||||
// amd
|
||||
define([], function () { return _factory(sharedObj); });
|
||||
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
// commonjs
|
||||
module.exports = _factory(sharedObj);
|
||||
} else {
|
||||
console.trace('perf-util defined in UNKNOWN context (neither requirejs or commonjs)');
|
||||
sharedObj.perf = _factory(sharedObj);
|
||||
}
|
||||
return sharedObj.MonacoPerformanceMarks;
|
||||
}
|
||||
|
||||
// This module can be loaded in an amd and commonjs-context.
|
||||
// Because we want both instances to use the same perf-data
|
||||
// we store them globally
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var sharedObj;
|
||||
if (typeof global === 'object') {
|
||||
// nodejs
|
||||
sharedObj = global;
|
||||
} else if (typeof self === 'object') {
|
||||
// browser
|
||||
sharedObj = self;
|
||||
} else {
|
||||
sharedObj = {};
|
||||
}
|
||||
|
||||
if (typeof define === 'function') {
|
||||
// amd
|
||||
define([], function () { return _factory(sharedObj); });
|
||||
} else if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
// commonjs
|
||||
module.exports = _factory(sharedObj);
|
||||
} else {
|
||||
console.trace('perf-util defined in UNKNOWN context (neither requirejs or commonjs)');
|
||||
sharedObj.perf = _factory(sharedObj);
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -27,37 +27,38 @@ export interface IProcessEnvironment {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface is intentionally not identical to node.js
|
||||
* process because it also works in sandboxed environments
|
||||
* where the process object is implemented differently. We
|
||||
* define the properties here that we need for `platform`
|
||||
* to work and nothing else.
|
||||
*/
|
||||
export interface INodeProcess {
|
||||
platform: 'win32' | 'linux' | 'darwin';
|
||||
platform: string;
|
||||
env: IProcessEnvironment;
|
||||
nextTick: Function;
|
||||
nextTick?: (callback: (...args: any[]) => void) => void;
|
||||
versions?: {
|
||||
electron?: string;
|
||||
};
|
||||
sandboxed?: boolean; // Electron
|
||||
sandboxed?: boolean;
|
||||
type?: string;
|
||||
cwd(): string;
|
||||
cwd: () => string;
|
||||
}
|
||||
|
||||
declare const process: INodeProcess;
|
||||
declare const global: any;
|
||||
declare const global: unknown;
|
||||
declare const self: unknown;
|
||||
|
||||
interface INavigator {
|
||||
userAgent: string;
|
||||
language: string;
|
||||
maxTouchPoints?: number;
|
||||
}
|
||||
declare const navigator: INavigator;
|
||||
declare const self: any;
|
||||
|
||||
const _globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {} as any);
|
||||
export const globals: any = (typeof self === 'object' ? self : typeof global === 'object' ? global : {});
|
||||
|
||||
let nodeProcess: INodeProcess | undefined = undefined;
|
||||
if (typeof process !== 'undefined') {
|
||||
// Native environment (non-sandboxed)
|
||||
nodeProcess = process;
|
||||
} else if (typeof _globals.vscode !== 'undefined') {
|
||||
} else if (typeof globals.vscode !== 'undefined') {
|
||||
// Native environment (sandboxed)
|
||||
nodeProcess = _globals.vscode.process;
|
||||
nodeProcess = globals.vscode.process;
|
||||
}
|
||||
|
||||
const isElectronRenderer = typeof nodeProcess?.versions?.electron === 'string' && nodeProcess.type === 'renderer';
|
||||
@@ -83,6 +84,13 @@ export const browserCodeLoadingCacheStrategy: 'none' | 'code' | 'bypassHeatCheck
|
||||
})();
|
||||
export const isPreferringBrowserCodeLoad = typeof browserCodeLoadingCacheStrategy === 'string';
|
||||
|
||||
interface INavigator {
|
||||
userAgent: string;
|
||||
language: string;
|
||||
maxTouchPoints?: number;
|
||||
}
|
||||
declare const navigator: INavigator;
|
||||
|
||||
// Web environment
|
||||
if (typeof navigator === 'object' && !isElectronRenderer) {
|
||||
_userAgent = navigator.userAgent;
|
||||
@@ -197,10 +205,8 @@ export const locale = _locale;
|
||||
*/
|
||||
export const translationsConfigFile = _translationsConfigFile;
|
||||
|
||||
export const globals: any = _globals;
|
||||
|
||||
interface ISetImmediate {
|
||||
(callback: (...args: any[]) => void): void;
|
||||
(callback: (...args: unknown[]) => void): void;
|
||||
}
|
||||
|
||||
export const setImmediate: ISetImmediate = (function defineSetImmediate() {
|
||||
@@ -235,11 +241,11 @@ export const setImmediate: ISetImmediate = (function defineSetImmediate() {
|
||||
globals.postMessage({ vscodeSetImmediateId: myId }, '*');
|
||||
};
|
||||
}
|
||||
if (nodeProcess && typeof nodeProcess.nextTick === 'function') {
|
||||
if (typeof nodeProcess?.nextTick === 'function') {
|
||||
return nodeProcess.nextTick.bind(nodeProcess);
|
||||
}
|
||||
const _promise = Promise.resolve();
|
||||
return (callback: (...args: any[]) => void) => _promise.then(callback);
|
||||
return (callback: (...args: unknown[]) => void) => _promise.then(callback);
|
||||
})();
|
||||
|
||||
export const enum OperatingSystem {
|
||||
|
||||
@@ -5,26 +5,27 @@
|
||||
|
||||
import { isWindows, isMacintosh, setImmediate, globals, INodeProcess } from 'vs/base/common/platform';
|
||||
|
||||
declare const process: INodeProcess;
|
||||
|
||||
let safeProcess: INodeProcess;
|
||||
let safeProcess: INodeProcess & { nextTick: (callback: (...args: any[]) => void) => void; };
|
||||
|
||||
// Native node.js environment
|
||||
declare const process: INodeProcess;
|
||||
if (typeof process !== 'undefined') {
|
||||
safeProcess = process;
|
||||
safeProcess = {
|
||||
get platform() { return process.platform; },
|
||||
get env() { return process.env; },
|
||||
cwd() { return process.env['VSCODE_CWD'] || process.cwd(); },
|
||||
nextTick(callback: (...args: any[]) => void): void { return process.nextTick!(callback); }
|
||||
};
|
||||
}
|
||||
|
||||
// Native sandbox environment
|
||||
else if (typeof globals.vscode !== 'undefined') {
|
||||
const sandboxProcess: INodeProcess = globals.vscode.process;
|
||||
safeProcess = {
|
||||
|
||||
// Supported
|
||||
get platform(): 'win32' | 'linux' | 'darwin' { return globals.vscode.process.platform; },
|
||||
get env() { return globals.vscode.process.env; },
|
||||
nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); },
|
||||
|
||||
// Unsupported
|
||||
cwd(): string { return globals.vscode.process.env['VSCODE_CWD'] || globals.vscode.process.execPath.substr(0, globals.vscode.process.execPath.lastIndexOf(globals.vscode.process.platform === 'win32' ? '\\' : '/')); }
|
||||
get platform() { return sandboxProcess.platform; },
|
||||
get env() { return sandboxProcess.env; },
|
||||
cwd() { return sandboxProcess.cwd(); },
|
||||
nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,16 +34,39 @@ else {
|
||||
safeProcess = {
|
||||
|
||||
// Supported
|
||||
get platform(): 'win32' | 'linux' | 'darwin' { return isWindows ? 'win32' : isMacintosh ? 'darwin' : 'linux'; },
|
||||
get platform() { return isWindows ? 'win32' : isMacintosh ? 'darwin' : 'linux'; },
|
||||
nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); },
|
||||
|
||||
// Unsupported
|
||||
get env() { return Object.create(null); },
|
||||
cwd(): string { return '/'; }
|
||||
cwd() { return '/'; }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides safe access to the `cwd` property in node.js, sandboxed or web
|
||||
* environments.
|
||||
*
|
||||
* Note: in web, this property is hardcoded to be `/`.
|
||||
*/
|
||||
export const cwd = safeProcess.cwd;
|
||||
|
||||
/**
|
||||
* Provides safe access to the `env` property in node.js, sandboxed or web
|
||||
* environments.
|
||||
*
|
||||
* Note: in web, this property is hardcoded to be `{}`.
|
||||
*/
|
||||
export const env = safeProcess.env;
|
||||
|
||||
/**
|
||||
* Provides safe access to the `platform` property in node.js, sandboxed or web
|
||||
* environments.
|
||||
*/
|
||||
export const platform = safeProcess.platform;
|
||||
|
||||
/**
|
||||
* Provides safe access to the `nextTick` method in node.js, sandboxed or web
|
||||
* environments.
|
||||
*/
|
||||
export const nextTick = safeProcess.nextTick;
|
||||
|
||||
@@ -20,6 +20,8 @@ export function buildReplaceStringWithCasePreserved(matches: string[] | null, pa
|
||||
return pattern.toLowerCase();
|
||||
} else if (strings.containsUppercaseCharacter(matches[0][0]) && pattern.length > 0) {
|
||||
return pattern[0].toUpperCase() + pattern.substr(1);
|
||||
} else if (matches[0][0].toUpperCase() !== matches[0][0] && pattern.length > 0) {
|
||||
return pattern[0].toLowerCase() + pattern.substr(1);
|
||||
} else {
|
||||
// we don't understand its pattern yet.
|
||||
return pattern;
|
||||
|
||||
@@ -101,19 +101,19 @@ export interface WriteableStream<T> extends ReadableStream<T> {
|
||||
/**
|
||||
* Signals an error to the consumer of the stream via the
|
||||
* on('error') handler if the stream is flowing.
|
||||
*
|
||||
* NOTE: call `end` to signal that the stream has ended,
|
||||
* this DOES NOT happen automatically from `error`.
|
||||
*/
|
||||
error(error: Error): void;
|
||||
|
||||
/**
|
||||
* Signals the end of the stream to the consumer. If the
|
||||
* result is not an error, will trigger the on('data') event
|
||||
* result is provided, will trigger the on('data') event
|
||||
* listener if the stream is flowing and buffer the data
|
||||
* otherwise until the stream is flowing.
|
||||
*
|
||||
* In case of an error, the on('error') event will be used
|
||||
* if the stream is flowing.
|
||||
*/
|
||||
end(result?: T | Error): void;
|
||||
end(result?: T): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,15 +267,13 @@ class WriteableStreamImpl<T> implements WriteableStream<T> {
|
||||
}
|
||||
}
|
||||
|
||||
end(result?: T | Error): void {
|
||||
end(result?: T): void {
|
||||
if (this.state.destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// end with data or error if provided
|
||||
if (result instanceof Error) {
|
||||
this.error(result);
|
||||
} else if (typeof result !== 'undefined') {
|
||||
// end with data if provided
|
||||
if (typeof result !== 'undefined') {
|
||||
this.write(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,13 @@ export function isNumber(obj: unknown): obj is number {
|
||||
return (typeof obj === 'number' && !isNaN(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns whether the provided parameter is an Iterable, casting to the given generic
|
||||
*/
|
||||
export function isIterable<T>(obj: unknown): obj is Iterable<T> {
|
||||
return !!obj && typeof (obj as any)[Symbol.iterator] === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns whether the provided parameter is a JavaScript Boolean or not.
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { promisify } from 'util';
|
||||
import { rtrim } from 'vs/base/common/strings';
|
||||
import { sep, join, normalize, dirname, basename } from 'vs/base/common/path';
|
||||
import { readdirSync } from 'vs/base/node/pfs';
|
||||
@@ -52,7 +53,11 @@ export function realcaseSync(path: string): string | null {
|
||||
|
||||
export async function realpath(path: string): Promise<string> {
|
||||
try {
|
||||
return await fs.promises.realpath(path);
|
||||
// DO NOT USE `fs.promises.realpath` here as it internally
|
||||
// calls `fs.native.realpath` which will result in subst
|
||||
// drives to be resolved to their target on Windows
|
||||
// https://github.com/microsoft/vscode/issues/118562
|
||||
return await promisify(fs.realpath)(path);
|
||||
} catch (error) {
|
||||
|
||||
// We hit an error calling fs.realpath(). Since fs.realpath() is doing some path normalization
|
||||
|
||||
@@ -6,27 +6,13 @@
|
||||
import * as fs from 'fs';
|
||||
import { tmpdir } from 'os';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
import { ResourceQueue } from 'vs/base/common/async';
|
||||
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { isEqualOrParent, isRootOrDriveLetter } from 'vs/base/common/extpath';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { normalizeNFC } from 'vs/base/common/normalization';
|
||||
|
||||
//#region Constants
|
||||
|
||||
// See https://github.com/microsoft/vscode/issues/30180
|
||||
const WIN32_MAX_FILE_SIZE = 300 * 1024 * 1024; // 300 MB
|
||||
const GENERAL_MAX_FILE_SIZE = 16 * 1024 * 1024 * 1024; // 16 GB
|
||||
|
||||
// See https://github.com/v8/v8/blob/5918a23a3d571b9625e5cce246bdd5b46ff7cd8b/src/heap/heap.cc#L149
|
||||
const WIN32_MAX_HEAP_SIZE = 700 * 1024 * 1024; // 700 MB
|
||||
const GENERAL_MAX_HEAP_SIZE = 700 * 2 * 1024 * 1024; // 1400 MB
|
||||
|
||||
export const MAX_FILE_SIZE = process.arch === 'ia32' ? WIN32_MAX_FILE_SIZE : GENERAL_MAX_FILE_SIZE;
|
||||
export const MAX_HEAP_SIZE = process.arch === 'ia32' ? WIN32_MAX_HEAP_SIZE : GENERAL_MAX_HEAP_SIZE;
|
||||
|
||||
//#endregion
|
||||
import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
//#region rimraf
|
||||
|
||||
@@ -361,6 +347,11 @@ export namespace SymlinkSupport {
|
||||
|
||||
//#region Write File
|
||||
|
||||
// According to node.js docs (https://nodejs.org/docs/v6.5.0/api/fs.html#fs_fs_writefile_file_data_options_callback)
|
||||
// it is not safe to call writeFile() on the same path multiple times without waiting for the callback to return.
|
||||
// Therefor we use a Queue on the path that is given to us to sequentialize calls to the same path properly.
|
||||
const writeQueues = new ResourceQueue();
|
||||
|
||||
/**
|
||||
* Same as `fs.writeFile` but with an additional call to
|
||||
* `fs.fdatasync` after writing to ensure changes are
|
||||
@@ -373,47 +364,13 @@ export function writeFile(path: string, data: Buffer, options?: IWriteFileOption
|
||||
export function writeFile(path: string, data: Uint8Array, options?: IWriteFileOptions): Promise<void>;
|
||||
export function writeFile(path: string, data: string | Buffer | Uint8Array, options?: IWriteFileOptions): Promise<void>;
|
||||
export function writeFile(path: string, data: string | Buffer | Uint8Array, options?: IWriteFileOptions): Promise<void> {
|
||||
const queueKey = toQueueKey(path);
|
||||
|
||||
return ensureWriteFileQueue(queueKey).queue(() => {
|
||||
return writeQueues.queueFor(URI.file(path), extUriBiasedIgnorePathCase).queue(() => {
|
||||
const ensuredOptions = ensureWriteOptions(options);
|
||||
|
||||
return new Promise((resolve, reject) => doWriteFileAndFlush(path, data, ensuredOptions, error => error ? reject(error) : resolve()));
|
||||
});
|
||||
}
|
||||
|
||||
// According to node.js docs (https://nodejs.org/docs/v6.5.0/api/fs.html#fs_fs_writefile_file_data_options_callback)
|
||||
// it is not safe to call writeFile() on the same path multiple times without waiting for the callback to return.
|
||||
// Therefor we use a Queue on the path that is given to us to sequentialize calls to the same path properly.
|
||||
const writeFilePathQueues: Map<string, Queue<void>> = new Map();
|
||||
|
||||
function toQueueKey(path: string): string {
|
||||
let queueKey = path;
|
||||
if (isWindows || isMacintosh) {
|
||||
queueKey = queueKey.toLowerCase(); // accommodate for case insensitive file systems
|
||||
}
|
||||
|
||||
return queueKey;
|
||||
}
|
||||
|
||||
function ensureWriteFileQueue(queueKey: string): Queue<void> {
|
||||
const existingWriteFileQueue = writeFilePathQueues.get(queueKey);
|
||||
if (existingWriteFileQueue) {
|
||||
return existingWriteFileQueue;
|
||||
}
|
||||
|
||||
const writeFileQueue = new Queue<void>();
|
||||
writeFilePathQueues.set(queueKey, writeFileQueue);
|
||||
|
||||
const onFinish = Event.once(writeFileQueue.onFinished);
|
||||
onFinish(() => {
|
||||
writeFilePathQueues.delete(queueKey);
|
||||
writeFileQueue.dispose();
|
||||
});
|
||||
|
||||
return writeFileQueue;
|
||||
}
|
||||
|
||||
export interface IWriteFileOptions {
|
||||
mode?: number;
|
||||
flag?: string;
|
||||
@@ -607,9 +564,6 @@ async function doCopy(source: string, target: string, payload: ICopyPayload): Pr
|
||||
|
||||
// Symlink
|
||||
if (symbolicLink) {
|
||||
if (symbolicLink.dangling) {
|
||||
return; // do not copy dangling symbolic links (https://github.com/microsoft/vscode/issues/111621)
|
||||
}
|
||||
|
||||
// Try to re-create the symlink unless `preserveSymlinks: false`
|
||||
if (payload.options.preserveSymlinks) {
|
||||
@@ -620,6 +574,10 @@ async function doCopy(source: string, target: string, payload: ICopyPayload): Pr
|
||||
console.warn('[node.js fs] copy of symlink failed: ', error);
|
||||
}
|
||||
}
|
||||
|
||||
if (symbolicLink.dangling) {
|
||||
return; // skip dangling symbolic links from here on (https://github.com/microsoft/vscode/issues/111621)
|
||||
}
|
||||
}
|
||||
|
||||
// Folder
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { env } from 'vs/base/common/process';
|
||||
|
||||
// This is required, since parseInt("7-preview") will return 7.
|
||||
const IntRegex: RegExp = /^\d+$/;
|
||||
@@ -103,17 +102,17 @@ function getProgramFilesPath(
|
||||
|
||||
if (!useAlternateBitness) {
|
||||
// Just use the native system bitness
|
||||
return env.ProgramFiles || null;
|
||||
return process.env.ProgramFiles || null;
|
||||
}
|
||||
|
||||
// We might be a 64-bit process looking for 32-bit program files
|
||||
if (processArch === Arch.x64) {
|
||||
return env['ProgramFiles(x86)'] || null;
|
||||
return process.env['ProgramFiles(x86)'] || null;
|
||||
}
|
||||
|
||||
// We might be a 32-bit process looking for 64-bit program files
|
||||
if (osArch === Arch.x64) {
|
||||
return env.ProgramW6432 || null;
|
||||
return process.env.ProgramW6432 || null;
|
||||
}
|
||||
|
||||
// We're a 32-bit process on 32-bit Windows, there is no other Program Files dir
|
||||
@@ -194,12 +193,12 @@ async function findPSCoreWindowsInstallation(
|
||||
|
||||
async function findPSCoreMsix({ findPreview }: { findPreview?: boolean } = {}): Promise<IPossiblePowerShellExe | null> {
|
||||
// We can't proceed if there's no LOCALAPPDATA path
|
||||
if (!env.LOCALAPPDATA) {
|
||||
if (!process.env.LOCALAPPDATA) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the base directory for MSIX application exe shortcuts
|
||||
const msixAppDir = path.join(env.LOCALAPPDATA, 'Microsoft', 'WindowsApps');
|
||||
const msixAppDir = path.join(process.env.LOCALAPPDATA, 'Microsoft', 'WindowsApps');
|
||||
|
||||
if (!await pfs.SymlinkSupport.existsDirectory(msixAppDir)) {
|
||||
return null;
|
||||
@@ -211,15 +210,11 @@ async function findPSCoreMsix({ findPreview }: { findPreview?: boolean } = {}):
|
||||
: { pwshMsixDirRegex: PwshMsixRegex, pwshMsixName: 'PowerShell (Store)' };
|
||||
|
||||
// We should find only one such application, so return on the first one
|
||||
try {
|
||||
for (const subdir of await pfs.readdir(msixAppDir)) {
|
||||
if (pwshMsixDirRegex.test(subdir)) {
|
||||
const pwshMsixPath = path.join(msixAppDir, subdir, 'pwsh.exe');
|
||||
return new PossiblePowerShellExe(pwshMsixPath, pwshMsixName);
|
||||
}
|
||||
for (const subdir of await pfs.readdir(msixAppDir)) {
|
||||
if (pwshMsixDirRegex.test(subdir)) {
|
||||
const pwshMsixPath = path.join(msixAppDir, subdir, 'pwsh.exe');
|
||||
return new PossiblePowerShellExe(pwshMsixPath, pwshMsixName);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`Unable to read MSIX directory (${msixAppDir}) because of the following error: ${err}`);
|
||||
}
|
||||
|
||||
// If we find nothing, return null
|
||||
@@ -234,7 +229,7 @@ function findPSCoreDotnetGlobalTool(): IPossiblePowerShellExe {
|
||||
|
||||
function findWinPS(): IPossiblePowerShellExe | null {
|
||||
const winPSPath = path.join(
|
||||
env.windir!,
|
||||
process.env.windir!,
|
||||
processArch === Arch.x86 && osArch !== Arch.x86 ? 'SysNative' : 'System32',
|
||||
'WindowsPowerShell', 'v1.0', 'powershell.exe');
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import * as fs from 'fs';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import * as cp from 'child_process';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as process from 'vs/base/common/process';
|
||||
import * as Types from 'vs/base/common/types';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
|
||||
@@ -13,7 +13,7 @@ import * as processes from 'vs/base/node/processes';
|
||||
* shell that the terminal uses by default.
|
||||
* @param p The platform to detect the shell of.
|
||||
*/
|
||||
export async function getSystemShell(p: platform.Platform, env = process.env as platform.IProcessEnvironment): Promise<string> {
|
||||
export async function getSystemShell(p: platform.Platform, env: platform.IProcessEnvironment): Promise<string> {
|
||||
if (p === platform.Platform.Windows) {
|
||||
if (platform.isWindows) {
|
||||
return getSystemShellWindows();
|
||||
@@ -25,7 +25,7 @@ export async function getSystemShell(p: platform.Platform, env = process.env as
|
||||
return getSystemShellUnixLike(p, env);
|
||||
}
|
||||
|
||||
export function getSystemShellSync(p: platform.Platform, env = process.env as platform.IProcessEnvironment): string {
|
||||
export function getSystemShellSync(p: platform.Platform, env: platform.IProcessEnvironment): string {
|
||||
if (p === platform.Platform.Windows) {
|
||||
if (platform.isWindows) {
|
||||
return getSystemShellWindowsSync(env);
|
||||
@@ -45,7 +45,7 @@ function getSystemShellUnixLike(p: platform.Platform, env: platform.IProcessEnvi
|
||||
}
|
||||
|
||||
if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) {
|
||||
let unixLikeTerminal: string;
|
||||
let unixLikeTerminal: string | undefined;
|
||||
if (platform.isWindows) {
|
||||
unixLikeTerminal = '/bin/bash'; // for WSL
|
||||
} else {
|
||||
|
||||
@@ -18,13 +18,31 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Platform, platform } from 'vs/base/common/platform';
|
||||
|
||||
export class NodeSocket implements ISocket {
|
||||
|
||||
public readonly socket: Socket;
|
||||
private readonly _errorListener: (err: any) => void;
|
||||
|
||||
constructor(socket: Socket) {
|
||||
this.socket = socket;
|
||||
this._errorListener = (err: any) => {
|
||||
if (err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
// An EPIPE exception at the wrong time can lead to a renderer process crash
|
||||
// so ignore the error since the socket will fire the close event soon anyways:
|
||||
// > https://nodejs.org/api/errors.html#errors_common_system_errors
|
||||
// > EPIPE (Broken pipe): A write on a pipe, socket, or FIFO for which there is no
|
||||
// > process to read the data. Commonly encountered at the net and http layers,
|
||||
// > indicative that the remote side of the stream being written to has been closed.
|
||||
return;
|
||||
}
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
};
|
||||
this.socket.on('error', this._errorListener);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.socket.off('error', this._errorListener);
|
||||
this.socket.destroy();
|
||||
}
|
||||
|
||||
@@ -62,7 +80,20 @@ export class NodeSocket implements ISocket {
|
||||
// > However, the false return value is only advisory and the writable stream will unconditionally
|
||||
// > accept and buffer chunk even if it has not been allowed to drain.
|
||||
try {
|
||||
this.socket.write(<Buffer>buffer.buffer);
|
||||
this.socket.write(<Buffer>buffer.buffer, (err: any) => {
|
||||
if (err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
// An EPIPE exception at the wrong time can lead to a renderer process crash
|
||||
// so ignore the error since the socket will fire the close event soon anyways:
|
||||
// > https://nodejs.org/api/errors.html#errors_common_system_errors
|
||||
// > EPIPE (Broken pipe): A write on a pipe, socket, or FIFO for which there is no
|
||||
// > process to read the data. Commonly encountered at the net and http layers,
|
||||
// > indicative that the remote side of the stream being written to has been closed.
|
||||
return;
|
||||
}
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
// An EPIPE exception at the wrong time can lead to a renderer process crash
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
|
||||
import { TestServiceClient } from './testService';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
|
||||
|
||||
function createClient(): Client {
|
||||
return new Client(getPathFromAmdModule(require, 'bootstrap-fork'), {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
position: absolute;
|
||||
width: 600px;
|
||||
z-index: 2000;
|
||||
padding-bottom: 6px;
|
||||
padding: 0 1px 6px 1px;
|
||||
left: 50%;
|
||||
margin-left: -300px;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/quickInput';
|
||||
import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS, ItemActivation } from 'vs/base/parts/quickinput/common/quickInput';
|
||||
import { IQuickPickItem, IPickOptions, IInputOptions, IQuickNavigateConfiguration, IQuickPick, IQuickInput, IQuickInputButton, IInputBox, IQuickPickItemButtonEvent, QuickPickInput, IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent, NO_KEY_MODS, ItemActivation, QuickInputHideReason, IQuickInputHideEvent } from 'vs/base/parts/quickinput/common/quickInput';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { QuickInputList, QuickInputListFocus } from './quickInputList';
|
||||
@@ -31,6 +31,7 @@ import { registerCodicon, Codicon } from 'vs/base/common/codicons';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
|
||||
export interface IQuickInputOptions {
|
||||
idPrefix: string;
|
||||
@@ -133,6 +134,7 @@ type Visibilities = {
|
||||
};
|
||||
|
||||
class QuickInput extends Disposable implements IQuickInput {
|
||||
protected static readonly noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel");
|
||||
|
||||
private _title: string | undefined;
|
||||
private _description: string | undefined;
|
||||
@@ -144,9 +146,14 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
private _busy = false;
|
||||
private _ignoreFocusOut = false;
|
||||
private _buttons: IQuickInputButton[] = [];
|
||||
protected noValidationMessage = QuickInput.noPromptMessage;
|
||||
private _validationMessage: string | undefined;
|
||||
private _lastValidationMessage: string | undefined;
|
||||
private _severity: Severity = Severity.Ignore;
|
||||
private _lastSeverity: Severity | undefined;
|
||||
private buttonsUpdated = false;
|
||||
private readonly onDidTriggerButtonEmitter = this._register(new Emitter<IQuickInputButton>());
|
||||
private readonly onDidHideEmitter = this._register(new Emitter<void>());
|
||||
private readonly onDidHideEmitter = this._register(new Emitter<IQuickInputHideEvent>());
|
||||
private readonly onDisposeEmitter = this._register(new Emitter<void>());
|
||||
|
||||
protected readonly visibleDisposables = this._register(new DisposableStore());
|
||||
@@ -241,6 +248,24 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
this.update();
|
||||
}
|
||||
|
||||
get validationMessage() {
|
||||
return this._validationMessage;
|
||||
}
|
||||
|
||||
set validationMessage(validationMessage: string | undefined) {
|
||||
this._validationMessage = validationMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
get severity() {
|
||||
return this._severity;
|
||||
}
|
||||
|
||||
set severity(severity: Severity) {
|
||||
this._severity = severity;
|
||||
this.update();
|
||||
}
|
||||
|
||||
readonly onDidTriggerButton = this.onDidTriggerButtonEmitter.event;
|
||||
|
||||
show(): void {
|
||||
@@ -266,10 +291,10 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
this.ui.hide();
|
||||
}
|
||||
|
||||
didHide(): void {
|
||||
didHide(reason = QuickInputHideReason.Other): void {
|
||||
this.visible = false;
|
||||
this.visibleDisposables.clear();
|
||||
this.onDidHideEmitter.fire();
|
||||
this.onDidHideEmitter.fire({ reason });
|
||||
}
|
||||
|
||||
readonly onDidHide = this.onDidHideEmitter.event;
|
||||
@@ -328,6 +353,16 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
this.ui.ignoreFocusOut = this.ignoreFocusOut;
|
||||
this.ui.setEnabled(this.enabled);
|
||||
this.ui.setContextKey(this.contextKey);
|
||||
|
||||
const validationMessage = this.validationMessage || this.noValidationMessage;
|
||||
if (this._lastValidationMessage !== validationMessage) {
|
||||
this._lastValidationMessage = validationMessage;
|
||||
dom.reset(this.ui.message, ...renderLabelWithIcons(escape(validationMessage)));
|
||||
}
|
||||
if (this._lastSeverity !== this.severity) {
|
||||
this._lastSeverity = this.severity;
|
||||
this.showMessageDecoration(this.severity);
|
||||
}
|
||||
}
|
||||
|
||||
private getTitle() {
|
||||
@@ -359,7 +394,7 @@ class QuickInput extends Disposable implements IQuickInput {
|
||||
|
||||
protected showMessageDecoration(severity: Severity) {
|
||||
this.ui.inputBox.showDecoration(severity);
|
||||
if (severity === Severity.Error) {
|
||||
if (severity !== Severity.Ignore) {
|
||||
const styles = this.ui.inputBox.stylesForType(severity);
|
||||
this.ui.message.style.color = styles.foreground ? `${styles.foreground}` : '';
|
||||
this.ui.message.style.backgroundColor = styles.background ? `${styles.background}` : '';
|
||||
@@ -414,8 +449,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
private readonly onDidTriggerItemButtonEmitter = this._register(new Emitter<IQuickPickItemButtonEvent<T>>());
|
||||
private _valueSelection: Readonly<[number, number]> | undefined;
|
||||
private valueSelectionUpdated = true;
|
||||
private _validationMessage: string | undefined;
|
||||
private _lastValidationMessage: string | undefined;
|
||||
private _ok: boolean | 'default' = 'default';
|
||||
private _customButton = false;
|
||||
private _customButtonLabel: string | undefined;
|
||||
@@ -587,15 +620,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this.update();
|
||||
}
|
||||
|
||||
get validationMessage() {
|
||||
return this._validationMessage;
|
||||
}
|
||||
|
||||
set validationMessage(validationMessage: string | undefined) {
|
||||
this._validationMessage = validationMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
get customButton() {
|
||||
return this._customButton;
|
||||
}
|
||||
@@ -964,12 +988,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
this.selectedItemsToConfirm = null;
|
||||
}
|
||||
}
|
||||
const validationMessage = this.validationMessage || '';
|
||||
if (this._lastValidationMessage !== validationMessage) {
|
||||
this._lastValidationMessage = validationMessage;
|
||||
dom.reset(this.ui.message, ...renderLabelWithIcons(escape(validationMessage)));
|
||||
this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore);
|
||||
}
|
||||
this.ui.customButton.label = this.customLabel || '';
|
||||
this.ui.customButton.element.title = this.customHover || '';
|
||||
this.ui.setComboboxAccessibility(true);
|
||||
@@ -987,18 +1005,12 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
|
||||
}
|
||||
|
||||
class InputBox extends QuickInput implements IInputBox {
|
||||
|
||||
private static readonly noPromptMessage = localize('inputModeEntry', "Press 'Enter' to confirm your input or 'Escape' to cancel");
|
||||
|
||||
private _value = '';
|
||||
private _valueSelection: Readonly<[number, number]> | undefined;
|
||||
private valueSelectionUpdated = true;
|
||||
private _placeholder: string | undefined;
|
||||
private _password = false;
|
||||
private _prompt: string | undefined;
|
||||
private noValidationMessage = InputBox.noPromptMessage;
|
||||
private _validationMessage: string | undefined;
|
||||
private _lastValidationMessage: string | undefined;
|
||||
private readonly onDidValueChangeEmitter = this._register(new Emitter<string>());
|
||||
private readonly onDidAcceptEmitter = this._register(new Emitter<void>());
|
||||
|
||||
@@ -1043,16 +1055,7 @@ class InputBox extends QuickInput implements IInputBox {
|
||||
this._prompt = prompt;
|
||||
this.noValidationMessage = prompt
|
||||
? localize('inputModeEntryDescription', "{0} (Press 'Enter' to confirm or 'Escape' to cancel)", prompt)
|
||||
: InputBox.noPromptMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
get validationMessage() {
|
||||
return this._validationMessage;
|
||||
}
|
||||
|
||||
set validationMessage(validationMessage: string | undefined) {
|
||||
this._validationMessage = validationMessage;
|
||||
: QuickInput.noPromptMessage;
|
||||
this.update();
|
||||
}
|
||||
|
||||
@@ -1100,12 +1103,7 @@ class InputBox extends QuickInput implements IInputBox {
|
||||
if (this.ui.inputBox.password !== this.password) {
|
||||
this.ui.inputBox.password = this.password;
|
||||
}
|
||||
const validationMessage = this.validationMessage || this.noValidationMessage;
|
||||
if (this._lastValidationMessage !== validationMessage) {
|
||||
this._lastValidationMessage = validationMessage;
|
||||
dom.reset(this.ui.message, ...renderLabelWithIcons(validationMessage));
|
||||
this.showMessageDecoration(this.validationMessage ? Severity.Error : Severity.Ignore);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1222,9 +1220,6 @@ export class QuickInputController extends Disposable {
|
||||
|
||||
const message = dom.append(extraContainer, $(`#${this.idPrefix}message.quick-input-message`));
|
||||
|
||||
const progressBar = new ProgressBar(container);
|
||||
progressBar.getContainer().classList.add('quick-input-progress');
|
||||
|
||||
const list = this._register(new QuickInputList(container, this.idPrefix + 'list', this.options));
|
||||
this._register(list.onChangedAllVisibleChecked(checked => {
|
||||
checkAll.checked = checked;
|
||||
@@ -1250,6 +1245,9 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
}));
|
||||
|
||||
const progressBar = new ProgressBar(container);
|
||||
progressBar.getContainer().classList.add('quick-input-progress');
|
||||
|
||||
const focusTracker = dom.trackFocus(container);
|
||||
this._register(focusTracker);
|
||||
this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, e => {
|
||||
@@ -1257,7 +1255,7 @@ export class QuickInputController extends Disposable {
|
||||
}, true));
|
||||
this._register(focusTracker.onDidBlur(() => {
|
||||
if (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) {
|
||||
this.hide();
|
||||
this.hide(QuickInputHideReason.Blur);
|
||||
}
|
||||
this.previousFocusElement = undefined;
|
||||
}));
|
||||
@@ -1273,7 +1271,7 @@ export class QuickInputController extends Disposable {
|
||||
break;
|
||||
case KeyCode.Escape:
|
||||
dom.EventHelper.stop(e, true);
|
||||
this.hide();
|
||||
this.hide(QuickInputHideReason.Gesture);
|
||||
break;
|
||||
case KeyCode.Tab:
|
||||
if (!event.altKey && !event.ctrlKey && !event.metaKey) {
|
||||
@@ -1320,8 +1318,8 @@ export class QuickInputController extends Disposable {
|
||||
message,
|
||||
customButtonContainer,
|
||||
customButton,
|
||||
progressBar,
|
||||
list,
|
||||
progressBar,
|
||||
onDidAccept: this.onDidAcceptEmitter.event,
|
||||
onDidCustom: this.onDidCustomEmitter.event,
|
||||
onDidTriggerButton: this.onDidTriggerButtonEmitter.event,
|
||||
@@ -1408,6 +1406,7 @@ export class QuickInputController extends Disposable {
|
||||
resolve(undefined);
|
||||
}),
|
||||
];
|
||||
input.title = options.title;
|
||||
input.canSelectMany = !!options.canPickMany;
|
||||
input.placeholder = options.placeHolder;
|
||||
input.ignoreFocusOut = !!options.ignoreFocusLost;
|
||||
@@ -1438,6 +1437,22 @@ export class QuickInputController extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private setValidationOnInput(input: IInputBox, validationResult: string | {
|
||||
content: string;
|
||||
severity: Severity;
|
||||
} | null | undefined) {
|
||||
if (validationResult && isString(validationResult)) {
|
||||
input.severity = Severity.Error;
|
||||
input.validationMessage = validationResult;
|
||||
} else if (validationResult && !isString(validationResult)) {
|
||||
input.severity = validationResult.severity;
|
||||
input.validationMessage = validationResult.content;
|
||||
} else {
|
||||
input.severity = Severity.Ignore;
|
||||
input.validationMessage = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
input(options: IInputOptions = {}, token: CancellationToken = CancellationToken.None): Promise<string | undefined> {
|
||||
return new Promise<string | undefined>((resolve) => {
|
||||
if (token.isCancellationRequested) {
|
||||
@@ -1458,7 +1473,7 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
validation.then(result => {
|
||||
if (value === validationValue) {
|
||||
input.validationMessage = result || undefined;
|
||||
this.setValidationOnInput(input, result);
|
||||
}
|
||||
});
|
||||
}),
|
||||
@@ -1469,11 +1484,11 @@ export class QuickInputController extends Disposable {
|
||||
validationValue = value;
|
||||
}
|
||||
validation.then(result => {
|
||||
if (!result) {
|
||||
if (!result || (!isString(result) && result.severity !== Severity.Error)) {
|
||||
resolve(value);
|
||||
input.hide();
|
||||
} else if (value === validationValue) {
|
||||
input.validationMessage = result;
|
||||
this.setValidationOnInput(input, result);
|
||||
}
|
||||
});
|
||||
}),
|
||||
@@ -1485,6 +1500,8 @@ export class QuickInputController extends Disposable {
|
||||
resolve(undefined);
|
||||
}),
|
||||
];
|
||||
|
||||
input.title = options.title;
|
||||
input.value = options.value || '';
|
||||
input.valueSelection = options.valueSelection;
|
||||
input.prompt = options.prompt;
|
||||
@@ -1600,7 +1617,7 @@ export class QuickInputController extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
hide() {
|
||||
hide(reason?: QuickInputHideReason) {
|
||||
const controller = this.controller;
|
||||
if (controller) {
|
||||
const focusChanged = !this.ui?.container.contains(document.activeElement);
|
||||
@@ -1615,7 +1632,7 @@ export class QuickInputController extends Disposable {
|
||||
this.options.returnFocus();
|
||||
}
|
||||
}
|
||||
controller.didHide();
|
||||
controller.didHide(reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IMatch } from 'vs/base/common/filters';
|
||||
import { IItemAccessor } from 'vs/base/common/fuzzyScorer';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
||||
export interface IQuickPickItemHighlights {
|
||||
label?: IMatch[];
|
||||
@@ -58,6 +59,11 @@ export interface IQuickNavigateConfiguration {
|
||||
|
||||
export interface IPickOptions<T extends IQuickPickItem> {
|
||||
|
||||
/**
|
||||
* an optional string to show as the title of the quick input
|
||||
*/
|
||||
title?: string;
|
||||
|
||||
/**
|
||||
* an optional string to show as placeholder in the input box to guide the user what she picks on
|
||||
*/
|
||||
@@ -115,6 +121,11 @@ export interface IPickOptions<T extends IQuickPickItem> {
|
||||
|
||||
export interface IInputOptions {
|
||||
|
||||
/**
|
||||
* an optional string to show as the title of the quick input
|
||||
*/
|
||||
title?: string;
|
||||
|
||||
/**
|
||||
* the value to prefill in the input box
|
||||
*/
|
||||
@@ -145,12 +156,34 @@ export interface IInputOptions {
|
||||
/**
|
||||
* an optional function that is used to validate user input.
|
||||
*/
|
||||
validateInput?: (input: string) => Promise<string | null | undefined>;
|
||||
validateInput?: (input: string) => Promise<string | null | undefined | { content: string, severity: Severity }>;
|
||||
}
|
||||
|
||||
export enum QuickInputHideReason {
|
||||
|
||||
/**
|
||||
* Focus moved away from the quick input.
|
||||
*/
|
||||
Blur = 1,
|
||||
|
||||
/**
|
||||
* An explicit user gesture, e.g. pressing Escape key.
|
||||
*/
|
||||
Gesture,
|
||||
|
||||
/**
|
||||
* Anything else.
|
||||
*/
|
||||
Other
|
||||
}
|
||||
|
||||
export interface IQuickInputHideEvent {
|
||||
reason: QuickInputHideReason;
|
||||
}
|
||||
|
||||
export interface IQuickInput extends IDisposable {
|
||||
|
||||
readonly onDidHide: Event<void>;
|
||||
readonly onDidHide: Event<IQuickInputHideEvent>;
|
||||
readonly onDispose: Event<void>;
|
||||
|
||||
title: string | undefined;
|
||||
@@ -301,6 +334,8 @@ export interface IInputBox extends IQuickInput {
|
||||
prompt: string | undefined;
|
||||
|
||||
validationMessage: string | undefined;
|
||||
|
||||
severity: Severity;
|
||||
}
|
||||
|
||||
export interface IQuickInputButton {
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
/**
|
||||
* A minimal set of methods exposed from Electron's `ipcRenderer`
|
||||
* to support communication to main process.
|
||||
*
|
||||
* @type {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
ipcRenderer: {
|
||||
|
||||
@@ -49,34 +51,46 @@
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
|
||||
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
on(channel, listener) {
|
||||
if (validateIPC(channel)) {
|
||||
ipcRenderer.on(channel, listener);
|
||||
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
|
||||
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
once(channel, listener) {
|
||||
if (validateIPC(channel)) {
|
||||
ipcRenderer.once(channel, listener);
|
||||
|
||||
return this;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: import('electron').IpcRendererEvent, ...args: any[]) => void} listener
|
||||
* @returns {import('../electron-sandbox/electronTypes').IpcRenderer}
|
||||
*/
|
||||
removeListener(channel, listener) {
|
||||
if (validateIPC(channel)) {
|
||||
ipcRenderer.removeListener(channel, listener);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {import('../electron-sandbox/globals').IpcMessagePort}
|
||||
*/
|
||||
ipcMessagePort: {
|
||||
|
||||
/**
|
||||
@@ -106,6 +120,8 @@
|
||||
|
||||
/**
|
||||
* Support for subset of methods of Electron's `webFrame` type.
|
||||
*
|
||||
* @type {import('../electron-sandbox/electronTypes').WebFrame}
|
||||
*/
|
||||
webFrame: {
|
||||
|
||||
@@ -121,6 +137,8 @@
|
||||
|
||||
/**
|
||||
* Support for subset of methods of Electron's `crashReporter` type.
|
||||
*
|
||||
* @type {import('../electron-sandbox/electronTypes').CrashReporter}
|
||||
*/
|
||||
crashReporter: {
|
||||
|
||||
@@ -138,6 +156,8 @@
|
||||
*
|
||||
* Note: when `sandbox` is enabled, the only properties available
|
||||
* are https://github.com/electron/electron/blob/master/docs/api/process.md#sandbox
|
||||
*
|
||||
* @type {import('../electron-sandbox/globals').ISandboxNodeProcess}
|
||||
*/
|
||||
process: {
|
||||
get platform() { return process.platform; },
|
||||
@@ -146,6 +166,21 @@
|
||||
get versions() { return process.versions; },
|
||||
get type() { return 'renderer'; },
|
||||
get execPath() { return process.execPath; },
|
||||
get sandboxed() { return process.sandboxed; },
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
cwd() {
|
||||
return process.env['VSCODE_CWD'] || process.execPath.substr(0, process.execPath.lastIndexOf(process.platform === 'win32' ? '\\' : '/'));
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {Promise<typeof process.env>}
|
||||
*/
|
||||
getShellEnv() {
|
||||
return shellEnv;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {{[key: string]: string}} userEnv
|
||||
@@ -164,20 +199,17 @@
|
||||
|
||||
/**
|
||||
* @param {string} type
|
||||
* @param {() => void} callback
|
||||
* @param {Function} callback
|
||||
* @returns {import('../electron-sandbox/globals').ISandboxNodeProcess}
|
||||
*/
|
||||
on(type, callback) {
|
||||
if (validateProcessEventType(type)) {
|
||||
// @ts-ignore
|
||||
process.on(type, callback);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Some information about the context we are running in.
|
||||
*/
|
||||
context: {
|
||||
get sandbox() { return process.sandboxed; }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -226,8 +258,8 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @type {Promise<void> | undefined} */
|
||||
let resolvedEnv = undefined;
|
||||
/** @type {Promise<typeof process.env> | undefined} */
|
||||
let shellEnv = undefined;
|
||||
|
||||
/**
|
||||
* If VSCode is not run from a terminal, we should resolve additional
|
||||
@@ -238,28 +270,29 @@
|
||||
* @param {{[key: string]: string}} userEnv
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function resolveEnv(userEnv) {
|
||||
if (!resolvedEnv) {
|
||||
async function resolveEnv(userEnv) {
|
||||
if (!shellEnv) {
|
||||
|
||||
// Apply `userEnv` directly
|
||||
Object.assign(process.env, userEnv);
|
||||
|
||||
// Resolve `shellEnv` from the main side
|
||||
resolvedEnv = new Promise(function (resolve) {
|
||||
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) {
|
||||
shellEnv = new Promise(function (resolve) {
|
||||
ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnvResult) {
|
||||
if (!process.env['VSCODE_SKIP_PROCESS_ENV_PATCHING'] /* TODO@bpasero for https://github.com/microsoft/vscode/issues/108804 */) {
|
||||
// Assign all keys of the shell environment to our process environment
|
||||
// But make sure that the user environment wins in the end over shell environment
|
||||
Object.assign(process.env, shellEnvResult, userEnv);
|
||||
}
|
||||
|
||||
// Assign all keys of the shell environment to our process environment
|
||||
// But make sure that the user environment wins in the end
|
||||
Object.assign(process.env, shellEnv, userEnv);
|
||||
|
||||
resolve();
|
||||
resolve({ ...process.env, ...shellEnvResult, ...userEnv });
|
||||
});
|
||||
|
||||
ipcRenderer.send('vscode:fetchShellEnv');
|
||||
});
|
||||
}
|
||||
|
||||
return resolvedEnv;
|
||||
await shellEnv;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { globals, IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { globals, INodeProcess, IProcessEnvironment } from 'vs/base/common/platform';
|
||||
import { ProcessMemoryInfo, CrashReporter, IpcRenderer, WebFrame } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes';
|
||||
|
||||
/**
|
||||
* In sandboxed renderers we cannot expose all of the `process` global of node.js
|
||||
*/
|
||||
export interface IPartialNodeProcess {
|
||||
export interface ISandboxNodeProcess extends INodeProcess {
|
||||
|
||||
/**
|
||||
* The process.platform property returns a string identifying the operating system platform
|
||||
* on which the Node.js process is running.
|
||||
*/
|
||||
readonly platform: 'win32' | 'linux' | 'darwin';
|
||||
readonly platform: string;
|
||||
|
||||
/**
|
||||
* The process.arch property returns a string identifying the CPU architecture
|
||||
@@ -24,9 +24,14 @@ export interface IPartialNodeProcess {
|
||||
readonly arch: string;
|
||||
|
||||
/**
|
||||
* The type will always be Electron renderer.
|
||||
* The type will always be `renderer`.
|
||||
*/
|
||||
readonly type: 'renderer';
|
||||
readonly type: string;
|
||||
|
||||
/**
|
||||
* Whether the process is sandboxed or not.
|
||||
*/
|
||||
readonly sandboxed: boolean;
|
||||
|
||||
/**
|
||||
* A list of versions for the current node.js/electron configuration.
|
||||
@@ -48,6 +53,11 @@ export interface IPartialNodeProcess {
|
||||
*/
|
||||
on: (type: string, callback: Function) => void;
|
||||
|
||||
/**
|
||||
* The current working directory of the process.
|
||||
*/
|
||||
cwd: () => string;
|
||||
|
||||
/**
|
||||
* Resolves with a ProcessMemoryInfo
|
||||
*
|
||||
@@ -62,9 +72,6 @@ export interface IPartialNodeProcess {
|
||||
* process on macOS.
|
||||
*/
|
||||
getProcessMemoryInfo: () => Promise<ProcessMemoryInfo>;
|
||||
}
|
||||
|
||||
export interface ISandboxNodeProcess extends IPartialNodeProcess {
|
||||
|
||||
/**
|
||||
* A custom method we add to `process`: Resolve the true process environment to use and
|
||||
@@ -84,14 +91,12 @@ export interface ISandboxNodeProcess extends IPartialNodeProcess {
|
||||
* set of environment in `process.env`.
|
||||
*/
|
||||
resolveEnv(userEnv: IProcessEnvironment): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ISandboxContext {
|
||||
|
||||
/**
|
||||
* Whether the renderer runs with `sandbox` enabled or not.
|
||||
* Returns a process environment that includes any shell environment even if the application
|
||||
* was not started from a shell / terminal / console.
|
||||
*/
|
||||
sandbox: boolean;
|
||||
getShellEnv(): Promise<IProcessEnvironment>;
|
||||
}
|
||||
|
||||
export interface IpcMessagePort {
|
||||
@@ -114,4 +119,3 @@ export const ipcMessagePort: IpcMessagePort = globals.vscode.ipcMessagePort;
|
||||
export const webFrame: WebFrame = globals.vscode.webFrame;
|
||||
export const crashReporter: CrashReporter = globals.vscode.crashReporter;
|
||||
export const process: ISandboxNodeProcess = globals.vscode.process;
|
||||
export const context: ISandboxContext = globals.vscode.context;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ipcRenderer, crashReporter, webFrame, process } from 'vs/base/parts/san
|
||||
|
||||
suite('Sandbox', () => {
|
||||
test('globals', () => {
|
||||
assert.ok(typeof ipcRenderer.invoke === 'function');
|
||||
assert.ok(typeof ipcRenderer.send === 'function');
|
||||
assert.ok(typeof crashReporter.addExtraParameter === 'function');
|
||||
assert.ok(typeof webFrame.setZoomLevel === 'function');
|
||||
assert.ok(typeof process.platform === 'string');
|
||||
|
||||
@@ -49,80 +49,6 @@ suite('Arrays', () => {
|
||||
assertMedian(13, [13, 4, 8], 2);
|
||||
});
|
||||
|
||||
test('stableSort', () => {
|
||||
function fill<T>(num: number, valueFn: () => T, arr: T[] = []): T[] {
|
||||
for (let i = 0; i < num; i++) {
|
||||
arr[i] = valueFn();
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
let data = fill(10000, () => ({ n: 1, m: counter++ }));
|
||||
|
||||
arrays.mergeSort(data, (a, b) => a.n - b.n);
|
||||
|
||||
let lastM = -1;
|
||||
for (const element of data) {
|
||||
assert.ok(lastM < element.m);
|
||||
lastM = element.m;
|
||||
}
|
||||
});
|
||||
|
||||
test('mergeSort', () => {
|
||||
let data = arrays.mergeSort([6, 5, 3, 1, 8, 7, 2, 4], (a, b) => a - b);
|
||||
assert.deepStrictEqual(data, [1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
});
|
||||
|
||||
test('mergeSort, sorted array', function () {
|
||||
let data = arrays.mergeSort([1, 2, 3, 4, 5, 6], (a, b) => a - b);
|
||||
assert.deepStrictEqual(data, [1, 2, 3, 4, 5, 6]);
|
||||
});
|
||||
|
||||
test('mergeSort, is stable', function () {
|
||||
|
||||
let numbers = arrays.mergeSort([33, 22, 11, 4, 99, 1], (a, b) => 0);
|
||||
assert.deepStrictEqual(numbers, [33, 22, 11, 4, 99, 1]);
|
||||
});
|
||||
|
||||
test('mergeSort, many random numbers', function () {
|
||||
|
||||
function compare(a: number, b: number) {
|
||||
if (a < b) {
|
||||
return -1;
|
||||
} else if (a > b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function assertSorted(array: number[]) {
|
||||
let last = array[0];
|
||||
for (let i = 1; i < array.length; i++) {
|
||||
let n = array[i];
|
||||
if (last > n) {
|
||||
assert.fail(JSON.stringify(array.slice(i - 10, i + 10)));
|
||||
}
|
||||
}
|
||||
}
|
||||
const MAX = 101;
|
||||
const data: number[][] = [];
|
||||
for (let i = 1; i < MAX; i++) {
|
||||
let array: number[] = [];
|
||||
for (let j = 0; j < 10 + i; j++) {
|
||||
array.push(Math.random() * 10e8 | 0);
|
||||
}
|
||||
data.push(array);
|
||||
}
|
||||
|
||||
for (const array of data) {
|
||||
arrays.mergeSort(array, compare);
|
||||
assertSorted(array);
|
||||
}
|
||||
});
|
||||
|
||||
test('sortedDiff', () => {
|
||||
function compare(a: number, b: number): number {
|
||||
return a - b;
|
||||
|
||||
@@ -88,7 +88,8 @@ suite('Buffer', () => {
|
||||
await timeout(0);
|
||||
stream.write(VSBuffer.fromString('Hello'));
|
||||
await timeout(0);
|
||||
stream.end(new Error());
|
||||
stream.error(new Error());
|
||||
stream.end();
|
||||
|
||||
assert.strictEqual(chunks.length, 1);
|
||||
assert.strictEqual(chunks[0].toString(), 'Hello');
|
||||
@@ -329,7 +330,8 @@ suite('Buffer', () => {
|
||||
await timeout(0);
|
||||
stream.write(VSBuffer.fromString('Hello'));
|
||||
await timeout(0);
|
||||
stream.end(new Error());
|
||||
stream.error(new Error());
|
||||
stream.end();
|
||||
|
||||
assert.strictEqual(chunks.length, 0);
|
||||
assert.strictEqual(ended, false);
|
||||
|
||||
@@ -66,6 +66,10 @@ suite('Stream', () => {
|
||||
stream.error(new Error());
|
||||
assert.strictEqual(error, true);
|
||||
|
||||
error = false;
|
||||
stream.error(new Error());
|
||||
assert.strictEqual(error, true);
|
||||
|
||||
stream.end('Final Bit');
|
||||
assert.strictEqual(chunks.length, 4);
|
||||
assert.strictEqual(chunks[3], 'Final Bit');
|
||||
@@ -86,6 +90,15 @@ suite('Stream', () => {
|
||||
assert.strictEqual(result, '');
|
||||
});
|
||||
|
||||
test('WriteableStream - end with error works', async () => {
|
||||
const reducer = (errors: Error[]) => errors.length > 0 ? errors[0] : null as unknown as Error;
|
||||
const stream = newWriteableStream<Error>(reducer);
|
||||
stream.end(new Error('error'));
|
||||
|
||||
const result = await consumeStream(stream, reducer);
|
||||
assert.ok(result instanceof Error);
|
||||
});
|
||||
|
||||
test('WriteableStream - removeListener', () => {
|
||||
const stream = newWriteableStream<string>(strings => strings.join());
|
||||
|
||||
|
||||
@@ -28,3 +28,14 @@ export function testRepeat(n: number, description: string, callback: (this: any)
|
||||
test(`${description} (iteration ${i})`, callback);
|
||||
}
|
||||
}
|
||||
|
||||
export async function assertThrowsAsync(block: () => any, message: string | Error = 'Missing expected exception'): Promise<void> {
|
||||
try {
|
||||
await block();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const err = message instanceof Error ? message : new Error(message);
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import { join } from 'vs/base/common/path';
|
||||
import { tmpdir } from 'os';
|
||||
import { promises } from 'fs';
|
||||
import { rimraf, writeFile } from 'vs/base/node/pfs';
|
||||
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
|
||||
suite('Crypto', () => {
|
||||
flakySuite('Crypto', () => {
|
||||
|
||||
let testDir: string;
|
||||
|
||||
|
||||
@@ -10,10 +10,9 @@ import { join, sep } from 'vs/base/common/path';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { copy, exists, move, readdir, readDirsInDir, rimraf, RimRafMode, rimrafSync, SymlinkSupport, writeFile, writeFileSync } from 'vs/base/node/pfs';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { canNormalize } from 'vs/base/common/normalization';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
import { flakySuite, getRandomTestPath, getPathFromAmdModule } from 'vs/base/test/node/testUtils';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
|
||||
flakySuite('PFS', function () {
|
||||
@@ -232,14 +231,19 @@ flakySuite('PFS', function () {
|
||||
assert.ok(!symbolicLink2);
|
||||
}
|
||||
|
||||
// Copy ignores dangling symlinks
|
||||
// Copy does not fail over dangling symlinks
|
||||
|
||||
await rimraf(copyTarget);
|
||||
await rimraf(symbolicLinkTarget);
|
||||
|
||||
await copy(symLink, copyTarget, { preserveSymlinks: true }); // this should not throw
|
||||
|
||||
assert.ok(!fs.existsSync(copyTarget));
|
||||
if (!isWindows) {
|
||||
const { symbolicLink } = await SymlinkSupport.stat(copyTarget);
|
||||
assert.ok(symbolicLink?.dangling);
|
||||
} else {
|
||||
assert.ok(!fs.existsSync(copyTarget));
|
||||
}
|
||||
});
|
||||
|
||||
test('copy handles symbolic links when the reference is inside source', async () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as cp from 'child_process';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as processes from 'vs/base/node/processes';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
|
||||
|
||||
function fork(id: string): cp.ChildProcess {
|
||||
const opts: any = {
|
||||
|
||||
@@ -5,12 +5,17 @@
|
||||
|
||||
import type { Suite } from 'mocha';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
|
||||
export function getRandomTestPath(tmpdir: string, ...segments: string[]): string {
|
||||
return join(tmpdir, ...segments, generateUuid());
|
||||
}
|
||||
|
||||
export function getPathFromAmdModule(requirefn: typeof require, relativePath: string): string {
|
||||
return URI.parse(requirefn.toUrl(relativePath)).fsPath;
|
||||
}
|
||||
|
||||
export function flakySuite(title: string, fn: (this: Suite) => void): Suite {
|
||||
return suite(title, function () {
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { readFileSync } from 'fs';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { getPathFromAmdModule } from 'vs/base/test/node/testUtils';
|
||||
|
||||
suite('URI - perf', function () {
|
||||
|
||||
|
||||
@@ -9,9 +9,8 @@ import { tmpdir } from 'os';
|
||||
import { promises } from 'fs';
|
||||
import { extract } from 'vs/base/node/zip';
|
||||
import { rimraf, exists } from 'vs/base/node/pfs';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { createCancelablePromise } from 'vs/base/common/async';
|
||||
import { getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
import { getRandomTestPath, getPathFromAmdModule } from 'vs/base/test/node/testUtils';
|
||||
|
||||
suite('Zip', () => {
|
||||
|
||||
|
||||
@@ -31,23 +31,15 @@ function getWorker(workerId: string, label: string): Worker | Promise<Worker> {
|
||||
}
|
||||
|
||||
// ESM-comment-begin
|
||||
export function getWorkerBootstrapUrl(scriptPath: string, label: string, forceDataUri: boolean = false): string {
|
||||
if (forceDataUri || /^((http:)|(https:)|(file:))/.test(scriptPath)) {
|
||||
const currentUrl = String(window.location);
|
||||
const currentOrigin = currentUrl.substr(0, currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length);
|
||||
if (forceDataUri || scriptPath.substring(0, currentOrigin.length) !== currentOrigin) {
|
||||
// this is the cross-origin case
|
||||
// i.e. the webpage is running at a different origin than where the scripts are loaded from
|
||||
const myPath = 'vs/base/worker/defaultWorkerFactory.js';
|
||||
const workerBaseUrl = require.toUrl(myPath).slice(0, -myPath.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
|
||||
const js = `/*${label}*/self.MonacoEnvironment={baseUrl: '${workerBaseUrl}'};importScripts('${scriptPath}');/*${label}*/`;
|
||||
if (forceDataUri) {
|
||||
const url = `data:text/javascript;charset=utf-8,${encodeURIComponent(js)}`;
|
||||
return url;
|
||||
}
|
||||
const blob = new Blob([js], { type: 'application/javascript' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
export function getWorkerBootstrapUrl(scriptPath: string, label: string): string {
|
||||
if (/^((http:)|(https:)|(file:))/.test(scriptPath) && scriptPath.substring(0, self.origin.length) !== self.origin) {
|
||||
// this is the cross-origin case
|
||||
// i.e. the webpage is running at a different origin than where the scripts are loaded from
|
||||
const myPath = 'vs/base/worker/defaultWorkerFactory.js';
|
||||
const workerBaseUrl = require.toUrl(myPath).slice(0, -myPath.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
|
||||
const js = `/*${label}*/self.MonacoEnvironment={baseUrl: '${workerBaseUrl}'};importScripts('${scriptPath}');/*${label}*/`;
|
||||
const blob = new Blob([js], { type: 'application/javascript' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
return scriptPath + '#' + label;
|
||||
}
|
||||
|
||||
@@ -10,36 +10,77 @@
|
||||
|
||||
const trustedTypesPolicy = (
|
||||
typeof self.trustedTypes?.createPolicy === 'function'
|
||||
? self.trustedTypes?.createPolicy('amdLoader', { createScriptURL: value => value })
|
||||
? self.trustedTypes?.createPolicy('amdLoader', {
|
||||
createScriptURL: value => value,
|
||||
createScript: (_, ...args: string[]) => {
|
||||
// workaround a chrome issue not allowing to create new functions
|
||||
// see https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor
|
||||
const fnArgs = args.slice(0, -1).join(',');
|
||||
const fnBody = args.pop()!.toString();
|
||||
const body = `(function anonymous(${fnArgs}) {\n${fnBody}\n})`;
|
||||
return body;
|
||||
}
|
||||
})
|
||||
: undefined
|
||||
);
|
||||
|
||||
if (typeof (<any>self).define !== 'function' || !(<any>self).define.amd) {
|
||||
let loaderSrc: string | TrustedScriptURL = monacoBaseUrl + 'vs/loader.js';
|
||||
if (trustedTypesPolicy) {
|
||||
loaderSrc = trustedTypesPolicy.createScriptURL(loaderSrc);
|
||||
}
|
||||
importScripts(loaderSrc as string);
|
||||
function loadAMDLoader() {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (typeof (<any>self).define === 'function' && (<any>self).define.amd) {
|
||||
return resolve();
|
||||
}
|
||||
const loaderSrc: string | TrustedScriptURL = monacoBaseUrl + 'vs/loader.js';
|
||||
|
||||
const isCrossOrigin = (/^((http:)|(https:)|(file:))/.test(loaderSrc) && loaderSrc.substring(0, self.origin.length) !== self.origin);
|
||||
if (!isCrossOrigin) {
|
||||
// use `fetch` if possible because `importScripts`
|
||||
// is synchronous and can lead to deadlocks on Safari
|
||||
fetch(loaderSrc).then((response) => {
|
||||
if (response.status !== 200) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
return response.text();
|
||||
}).then((text) => {
|
||||
text = `${text}\n//# sourceURL=${loaderSrc}`;
|
||||
const func = (
|
||||
trustedTypesPolicy
|
||||
? self.eval(trustedTypesPolicy.createScript('', text) as unknown as string)
|
||||
: new Function(text)
|
||||
);
|
||||
func.call(self);
|
||||
resolve();
|
||||
}).then(undefined, reject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (trustedTypesPolicy) {
|
||||
importScripts(trustedTypesPolicy.createScriptURL(loaderSrc) as unknown as string);
|
||||
} else {
|
||||
importScripts(loaderSrc as string);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
require.config({
|
||||
baseUrl: monacoBaseUrl,
|
||||
catchError: true,
|
||||
trustedTypesPolicy,
|
||||
});
|
||||
const loadCode = function (moduleId: string) {
|
||||
loadAMDLoader().then(() => {
|
||||
require.config({
|
||||
baseUrl: monacoBaseUrl,
|
||||
catchError: true,
|
||||
trustedTypesPolicy,
|
||||
});
|
||||
require([moduleId], function (ws) {
|
||||
setTimeout(function () {
|
||||
let messageHandler = ws.create((msg: any, transfer?: Transferable[]) => {
|
||||
(<any>self).postMessage(msg, transfer);
|
||||
}, null);
|
||||
|
||||
let loadCode = function (moduleId: string) {
|
||||
require([moduleId], function (ws) {
|
||||
setTimeout(function () {
|
||||
let messageHandler = ws.create((msg: any, transfer?: Transferable[]) => {
|
||||
(<any>self).postMessage(msg, transfer);
|
||||
}, null);
|
||||
|
||||
self.onmessage = (e: MessageEvent) => messageHandler.onmessage(e.data);
|
||||
while (beforeReadyMessages.length > 0) {
|
||||
self.onmessage(beforeReadyMessages.shift()!);
|
||||
}
|
||||
}, 0);
|
||||
self.onmessage = (e: MessageEvent) => messageHandler.onmessage(e.data);
|
||||
while (beforeReadyMessages.length > 0) {
|
||||
self.onmessage(beforeReadyMessages.shift()!);
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
80
src/vs/code/browser/workbench/workbench-web.html
Normal file
80
src/vs/code/browser/workbench/workbench-web.html
Normal file
@@ -0,0 +1,80 @@
|
||||
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
performance.mark('code/didStartRenderer')
|
||||
</script>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
|
||||
<!-- Workbench Configuration -->
|
||||
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}">
|
||||
|
||||
<!-- Workbench Auth Session -->
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/favicon.ico" type="image/x-icon" />
|
||||
<link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/manifest.json">
|
||||
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
<script>
|
||||
var baseUrl = '{{WORKBENCH_WEB_BASE_URL}}';
|
||||
self.require = {
|
||||
baseUrl: `${baseUrl}/out`,
|
||||
recordStats: true,
|
||||
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
|
||||
createScriptURL(value) {
|
||||
if(value.startsWith(baseUrl)) {
|
||||
return value;
|
||||
}
|
||||
throw new Error(`Invalid script url: ${value}`)
|
||||
}
|
||||
}),
|
||||
paths: {
|
||||
'vscode-textmate': `${baseUrl}/node_modules/vscode-textmate/release/main`,
|
||||
'vscode-oniguruma': `${baseUrl}/node_modules/vscode-oniguruma/release/main`,
|
||||
'xterm': `${baseUrl}/node_modules/xterm/lib/xterm.js`,
|
||||
'xterm-addon-search': `${baseUrl}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
|
||||
'xterm-addon-unicode11': `${baseUrl}/node_modules/xterm-addon-unicode11/lib/xterm-addon-unicode11.js`,
|
||||
'xterm-addon-webgl': `${baseUrl}/node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js`,
|
||||
'tas-client-umd': `${baseUrl}/node_modules/tas-client-umd/lib/tas-client-umd.js`,
|
||||
'iconv-lite-umd': `${baseUrl}/node_modules/iconv-lite-umd/lib/iconv-lite-umd.js`,
|
||||
'jschardet': `${baseUrl}/node_modules/jschardet/dist/jschardet.min.js`,
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
|
||||
<script>
|
||||
performance.mark('code/willLoadWorkbenchMain');
|
||||
</script>
|
||||
|
||||
<script>
|
||||
if ("{{WORKBENCH_DEV}}" === "true") {
|
||||
const workbench = document.createElement('script');
|
||||
workbench.innerText = "require(['vs/code/browser/workbench/workbench'], function() {});";
|
||||
document.body.appendChild(workbench);
|
||||
} else {
|
||||
const nls = document.createElement('script');
|
||||
nls.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.nls.js');
|
||||
document.body.appendChild(nls);
|
||||
|
||||
const api = document.createElement('script');
|
||||
api.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.api.js');
|
||||
document.body.appendChild(api);
|
||||
|
||||
const workbench = document.createElement('script');
|
||||
workbench.setAttribute('src', '{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.js');
|
||||
document.body.appendChild(workbench);
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
@@ -7,7 +7,7 @@ import * as fs from 'fs';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -32,9 +32,14 @@ interface LanguagePackFile {
|
||||
|
||||
export class LanguagePackCachedDataCleaner extends Disposable {
|
||||
|
||||
private readonly _DataMaxAge = this._productService.quality !== 'stable'
|
||||
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
|
||||
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
|
||||
|
||||
constructor(
|
||||
@INativeEnvironmentService private readonly _environmentService: INativeEnvironmentService,
|
||||
@ILogService private readonly _logService: ILogService
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@IProductService private readonly _productService: IProductService
|
||||
) {
|
||||
super();
|
||||
// We have no Language pack support for dev version (run from source)
|
||||
@@ -48,9 +53,6 @@ export class LanguagePackCachedDataCleaner extends Disposable {
|
||||
let handle: any = setTimeout(async () => {
|
||||
handle = undefined;
|
||||
this._logService.info('Starting to clean up unused language packs.');
|
||||
const maxAge = product.nameLong.indexOf('Insiders') >= 0
|
||||
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
|
||||
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
|
||||
try {
|
||||
const installed: IStringDictionary<boolean> = Object.create(null);
|
||||
const metaData: LanguagePackFile = JSON.parse(await fs.promises.readFile(path.join(this._environmentService.userDataPath, 'languagepacks.json'), 'utf8'));
|
||||
@@ -84,7 +86,7 @@ export class LanguagePackCachedDataCleaner extends Disposable {
|
||||
const stat = await fs.promises.stat(candidate);
|
||||
if (stat.isDirectory()) {
|
||||
const diff = now - stat.mtime.getTime();
|
||||
if (diff > maxAge) {
|
||||
if (diff > this._DataMaxAge) {
|
||||
this._logService.info('Removing language pack cache entry: ', path.join(packEntry, entry));
|
||||
await pfs.rimraf(candidate);
|
||||
}
|
||||
|
||||
@@ -8,18 +8,19 @@ import { basename, dirname, join } from 'vs/base/common/path';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { readdir, rimraf } from 'vs/base/node/pfs';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
|
||||
export class NodeCachedDataCleaner {
|
||||
|
||||
private static readonly _DataMaxAge = product.nameLong.indexOf('Insiders') >= 0
|
||||
private readonly _DataMaxAge = this.productService.quality !== 'stable'
|
||||
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
|
||||
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
|
||||
|
||||
private readonly _disposables = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
private readonly nodeCachedDataDir: string | undefined
|
||||
private readonly nodeCachedDataDir: string | undefined,
|
||||
@IProductService private readonly productService: IProductService
|
||||
) {
|
||||
this._manageCachedDataSoon();
|
||||
}
|
||||
@@ -61,7 +62,7 @@ export class NodeCachedDataCleaner {
|
||||
// * only when old enough
|
||||
if (stats.isDirectory()) {
|
||||
const diff = now - stats.mtime.getTime();
|
||||
if (diff > NodeCachedDataCleaner._DataMaxAge) {
|
||||
if (diff > this._DataMaxAge) {
|
||||
return rimraf(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { StaticRouter, ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { ExtensionManagementChannel, ExtensionTipsChannel } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
|
||||
import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
@@ -23,7 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { RequestService } from 'vs/platform/request/browser/requestService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ICustomEndpointTelemetryService, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { combinedAppender, NullTelemetryService, ITelemetryAppender, NullAppender } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc';
|
||||
@@ -58,7 +58,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
|
||||
import { UserDataAutoSyncService } from 'vs/platform/userDataSync/electron-sandbox/userDataAutoSyncService';
|
||||
import { NativeStorageService2 } from 'vs/platform/storage/electron-sandbox/storageService2';
|
||||
import { NativeStorageService } from 'vs/platform/storage/electron-sandbox/storageService';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
|
||||
import { UserDataSyncResourceEnablementService } from 'vs/platform/userDataSync/common/userDataSyncResourceEnablementService';
|
||||
@@ -81,9 +81,12 @@ import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/err
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { TerminalIpcChannels } from 'vs/platform/terminal/common/terminal';
|
||||
import { LocalPtyService } from 'vs/platform/terminal/electron-browser/localPtyService';
|
||||
import { PtyHostService } from 'vs/platform/terminal/node/ptyHostService';
|
||||
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
|
||||
import { UserDataSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncServiceIpc';
|
||||
import { IChecksumService } from 'vs/platform/checksum/common/checksumService';
|
||||
import { ChecksumService } from 'vs/platform/checksum/node/checksumService';
|
||||
import { CustomEndpointTelemetryService } from 'vs/platform/telemetry/node/customEndpointTelemetryService';
|
||||
|
||||
class SharedProcessMain extends Disposable {
|
||||
|
||||
@@ -129,7 +132,7 @@ class SharedProcessMain extends Disposable {
|
||||
|
||||
// Instantiate Contributions
|
||||
this._register(combinedDisposable(
|
||||
new NodeCachedDataCleaner(this.configuration.nodeCachedDataDir),
|
||||
instantiationService.createInstance(NodeCachedDataCleaner, this.configuration.nodeCachedDataDir),
|
||||
instantiationService.createInstance(LanguagePackCachedDataCleaner),
|
||||
instantiationService.createInstance(StorageDataCleaner, this.configuration.backupWorkspacesPath),
|
||||
instantiationService.createInstance(LogsDataCleaner),
|
||||
@@ -141,9 +144,12 @@ class SharedProcessMain extends Disposable {
|
||||
private async initServices(): Promise<IInstantiationService> {
|
||||
const services = new ServiceCollection();
|
||||
|
||||
// Product
|
||||
const productService = { _serviceBrand: undefined, ...product };
|
||||
services.set(IProductService, productService);
|
||||
|
||||
// Environment
|
||||
const environmentService = new NativeEnvironmentService(this.configuration.args);
|
||||
services.set(IEnvironmentService, environmentService);
|
||||
const environmentService = new NativeEnvironmentService(this.configuration.args, productService);
|
||||
services.set(INativeEnvironmentService, environmentService);
|
||||
|
||||
// Log
|
||||
@@ -175,18 +181,18 @@ class SharedProcessMain extends Disposable {
|
||||
await configurationService.initialize();
|
||||
|
||||
// Storage (global access only)
|
||||
const storageService = new NativeStorageService2(undefined, mainProcessService, environmentService);
|
||||
const storageService = new NativeStorageService(undefined, mainProcessService, environmentService);
|
||||
services.set(IStorageService, storageService);
|
||||
|
||||
await storageService.initialize();
|
||||
this._register(toDisposable(() => storageService.flush()));
|
||||
|
||||
// Product
|
||||
services.set(IProductService, { _serviceBrand: undefined, ...product });
|
||||
|
||||
// Request
|
||||
services.set(IRequestService, new SyncDescriptor(RequestService));
|
||||
|
||||
// Checksum
|
||||
services.set(IChecksumService, new SyncDescriptor(ChecksumService));
|
||||
|
||||
// Native Host
|
||||
const nativeHostService = ProxyChannel.toService<INativeHostService>(mainProcessService.getChannel('nativeHost'), { context: this.configuration.windowId });
|
||||
services.set(INativeHostService, nativeHostService);
|
||||
@@ -208,19 +214,19 @@ class SharedProcessMain extends Disposable {
|
||||
|
||||
let telemetryService: ITelemetryService;
|
||||
let telemetryAppender: ITelemetryAppender;
|
||||
if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
|
||||
if (!extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
|
||||
telemetryAppender = new TelemetryLogAppender(loggerService, environmentService);
|
||||
|
||||
// Application Insights
|
||||
if (product.aiConfig && product.aiConfig.asimovKey && isBuilt) {
|
||||
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey);
|
||||
if (productService.aiConfig && productService.aiConfig.asimovKey && isBuilt) {
|
||||
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey);
|
||||
this._register(toDisposable(() => appInsightsAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
telemetryAppender = combinedAppender(appInsightsAppender, telemetryAppender);
|
||||
}
|
||||
|
||||
telemetryService = new TelemetryService({
|
||||
appender: telemetryAppender,
|
||||
commonProperties: resolveCommonProperties(fileService, release(), process.arch, product.commit, product.version, this.configuration.machineId, product.msftInternalDomains, installSourcePath),
|
||||
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, this.configuration.machineId, productService.msftInternalDomains, installSourcePath),
|
||||
sendErrorTelemetry: true,
|
||||
piiPaths: [appRoot, extensionsPath]
|
||||
}, configurationService);
|
||||
@@ -232,6 +238,10 @@ class SharedProcessMain extends Disposable {
|
||||
this.server.registerChannel('telemetryAppender', new TelemetryAppenderChannel(telemetryAppender));
|
||||
services.set(ITelemetryService, telemetryService);
|
||||
|
||||
// Custom Endpoint Telemetry
|
||||
const customEndpointTelemetryService = new CustomEndpointTelemetryService(configurationService, telemetryService);
|
||||
services.set(ICustomEndpointTelemetryService, customEndpointTelemetryService);
|
||||
|
||||
// Extension Management
|
||||
services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService));
|
||||
|
||||
@@ -263,8 +273,7 @@ class SharedProcessMain extends Disposable {
|
||||
services.set(IUserDataSyncService, new SyncDescriptor(UserDataSyncService));
|
||||
|
||||
// Terminal
|
||||
const localPtyService = this._register(new LocalPtyService(logService));
|
||||
services.set(ILocalPtyService, localPtyService);
|
||||
services.set(ILocalPtyService, this._register(new PtyHostService(logService)));
|
||||
|
||||
return new InstantiationService(services);
|
||||
}
|
||||
@@ -287,10 +296,18 @@ class SharedProcessMain extends Disposable {
|
||||
const extensionTipsChannel = new ExtensionTipsChannel(accessor.get(IExtensionTipsService));
|
||||
this.server.registerChannel('extensionTipsService', extensionTipsChannel);
|
||||
|
||||
// Checksum
|
||||
const checksumChannel = ProxyChannel.fromService(accessor.get(IChecksumService));
|
||||
this.server.registerChannel('checksum', checksumChannel);
|
||||
|
||||
// Settings Sync
|
||||
const userDataSyncMachineChannel = new UserDataSyncMachinesServiceChannel(accessor.get(IUserDataSyncMachinesService));
|
||||
this.server.registerChannel('userDataSyncMachines', userDataSyncMachineChannel);
|
||||
|
||||
// Custom Endpoint Telemetry
|
||||
const customEndpointTelemetryChannel = ProxyChannel.fromService(accessor.get(ICustomEndpointTelemetryService));
|
||||
this.server.registerChannel('customEndpointTelemetry', customEndpointTelemetryChannel);
|
||||
|
||||
const userDataSyncAccountChannel = new UserDataSyncAccountServiceChannel(accessor.get(IUserDataSyncAccountService));
|
||||
this.server.registerChannel('userDataSyncAccount', userDataSyncAccountChannel);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtil
|
||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
|
||||
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
|
||||
import { FileProtocolHandler } from 'vs/code/electron-main/protocol';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
@@ -80,13 +80,14 @@ import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encry
|
||||
import { ActiveWindowManager } from 'vs/platform/windows/node/windowTracker';
|
||||
import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService';
|
||||
import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper';
|
||||
import { isEqualOrParent } from 'vs/base/common/extpath';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { IExtensionUrlTrustService } from 'vs/platform/extensionManagement/common/extensionUrlTrust';
|
||||
import { ExtensionUrlTrustService } from 'vs/platform/extensionManagement/node/extensionUrlTrustService';
|
||||
import { once } from 'vs/base/common/functional';
|
||||
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
|
||||
/**
|
||||
* The main VS Code application. There will only ever be one instance,
|
||||
@@ -105,7 +106,8 @@ export class CodeApplication extends Disposable {
|
||||
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IStateService private readonly stateService: IStateService,
|
||||
@IFileService private readonly fileService: IFileService
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IProductService private readonly productService: IProductService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -418,7 +420,7 @@ export class CodeApplication extends Disposable {
|
||||
// This will help Windows to associate the running program with
|
||||
// any shortcut that is pinned to the taskbar and prevent showing
|
||||
// two icons in the taskbar for the same app.
|
||||
const win32AppUserModelId = product.win32AppUserModelId;
|
||||
const win32AppUserModelId = this.productService.win32AppUserModelId;
|
||||
if (isWindows && win32AppUserModelId) {
|
||||
app.setAppUserModelId(win32AppUserModelId);
|
||||
}
|
||||
@@ -559,9 +561,6 @@ export class CodeApplication extends Disposable {
|
||||
// Keyboard Layout
|
||||
services.set(IKeyboardLayoutMainService, new SyncDescriptor(KeyboardLayoutMainService));
|
||||
|
||||
// Display
|
||||
services.set(IDisplayMainService, new SyncDescriptor(DisplayMainService));
|
||||
|
||||
// Native Host
|
||||
services.set(INativeHostMainService, new SyncDescriptor(NativeHostMainService, [sharedProcess]));
|
||||
|
||||
@@ -590,10 +589,10 @@ export class CodeApplication extends Disposable {
|
||||
services.set(IURLService, new SyncDescriptor(NativeURLService));
|
||||
|
||||
// Telemetry
|
||||
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!product.enableTelemetry) {
|
||||
if (!this.environmentMainService.isExtensionDevelopment && !this.environmentMainService.args['disable-telemetry'] && !!this.productService.enableTelemetry) {
|
||||
const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender')));
|
||||
const appender = new TelemetryAppenderClient(channel);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, product.commit, product.version, machineId, product.msftInternalDomains, this.environmentMainService.installSourcePath);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), process.arch, this.productService.commit, this.productService.version, machineId, this.productService.msftInternalDomains, this.environmentMainService.installSourcePath);
|
||||
const piiPaths = [this.environmentMainService.appRoot, this.environmentMainService.extensionsPath];
|
||||
const config: ITelemetryServiceConfig = { appender, commonProperties, piiPaths, sendErrorTelemetry: true };
|
||||
|
||||
@@ -629,14 +628,14 @@ export class CodeApplication extends Disposable {
|
||||
const encryptionChannel = ProxyChannel.fromService(accessor.get(IEncryptionMainService));
|
||||
mainProcessElectronServer.registerChannel('encryption', encryptionChannel);
|
||||
|
||||
// Signing
|
||||
const signChannel = ProxyChannel.fromService(accessor.get(ISignService));
|
||||
mainProcessElectronServer.registerChannel('sign', signChannel);
|
||||
|
||||
// Keyboard Layout
|
||||
const keyboardLayoutChannel = ProxyChannel.fromService(accessor.get(IKeyboardLayoutMainService));
|
||||
mainProcessElectronServer.registerChannel('keyboardLayout', keyboardLayoutChannel);
|
||||
|
||||
// Display
|
||||
const displayChannel = ProxyChannel.fromService(accessor.get(IDisplayMainService));
|
||||
mainProcessElectronServer.registerChannel('display', displayChannel);
|
||||
|
||||
// Native host (main & shared process)
|
||||
this.nativeHostMainService = accessor.get(INativeHostMainService);
|
||||
const nativeHostChannel = ProxyChannel.fromService(this.nativeHostMainService);
|
||||
@@ -751,6 +750,7 @@ export class CodeApplication extends Disposable {
|
||||
cli: { ...environmentService.args },
|
||||
urisToOpen: [windowOpenableFromProtocolLink],
|
||||
gotoLineMode: true
|
||||
/* remoteAuthority will be determined based on windowOpenableFromProtocolLink */
|
||||
});
|
||||
|
||||
window.focus(); // this should help ensuring that the right window gets focus when multiple are opened
|
||||
@@ -765,7 +765,8 @@ export class CodeApplication extends Disposable {
|
||||
context: OpenContext.API,
|
||||
cli: { ...environmentService.args },
|
||||
forceEmpty: true,
|
||||
gotoLineMode: true
|
||||
gotoLineMode: true,
|
||||
remoteAuthority: getRemoteAuthority(uri)
|
||||
});
|
||||
|
||||
await window.ready();
|
||||
@@ -789,7 +790,7 @@ export class CodeApplication extends Disposable {
|
||||
urlService.registerHandler(new URLHandlerChannelClient(urlHandlerChannel));
|
||||
|
||||
// Watch Electron URLs and forward them to the UrlService
|
||||
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentMainService));
|
||||
this._register(new ElectronURLListener(pendingProtocolLinksToHandle, urlService, windowsMainService, this.environmentMainService, this.productService));
|
||||
|
||||
// Open our first window
|
||||
const args = this.environmentMainService.args;
|
||||
@@ -800,6 +801,7 @@ export class CodeApplication extends Disposable {
|
||||
const hasFileURIs = !!args['file-uri'];
|
||||
const noRecentEntry = args['skip-add-to-recently-opened'] === true;
|
||||
const waitMarkerFileURI = args.wait && args.waitMarkerFilePath ? URI.file(args.waitMarkerFilePath) : undefined;
|
||||
const remoteAuthority = args.remote || undefined;
|
||||
|
||||
// check for a pending window to open from URI
|
||||
// e.g. when running code with --open-uri from
|
||||
@@ -811,6 +813,7 @@ export class CodeApplication extends Disposable {
|
||||
urisToOpen: pendingWindowOpenablesFromProtocolLinks,
|
||||
gotoLineMode: true,
|
||||
initialStartup: true
|
||||
/* remoteAuthority will be determined based on pendingWindowOpenablesFromProtocolLinks */
|
||||
});
|
||||
}
|
||||
|
||||
@@ -823,7 +826,8 @@ export class CodeApplication extends Disposable {
|
||||
forceEmpty: true,
|
||||
noRecentEntry,
|
||||
waitMarkerFileURI,
|
||||
initialStartup: true
|
||||
initialStartup: true,
|
||||
remoteAuthority
|
||||
});
|
||||
}
|
||||
|
||||
@@ -835,7 +839,8 @@ export class CodeApplication extends Disposable {
|
||||
urisToOpen: macOpenFiles.map(file => this.getWindowOpenableFromPathSync(file)),
|
||||
noRecentEntry,
|
||||
waitMarkerFileURI,
|
||||
initialStartup: true
|
||||
initialStartup: true,
|
||||
/* remoteAuthority will be determined based on macOpenFiles */
|
||||
});
|
||||
}
|
||||
|
||||
@@ -848,21 +853,22 @@ export class CodeApplication extends Disposable {
|
||||
noRecentEntry,
|
||||
waitMarkerFileURI,
|
||||
gotoLineMode: args.goto,
|
||||
initialStartup: true
|
||||
initialStartup: true,
|
||||
remoteAuthority
|
||||
});
|
||||
}
|
||||
|
||||
private shouldBlockURI(uri: URI): boolean {
|
||||
if (uri.authority === Schemas.file && isWindows) {
|
||||
const res = dialog.showMessageBoxSync({
|
||||
title: product.nameLong,
|
||||
title: this.productService.nameLong,
|
||||
type: 'question',
|
||||
buttons: [
|
||||
mnemonicButtonLabel(localize({ key: 'open', comment: ['&& denotes a mnemonic'] }, "&&Yes")),
|
||||
mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&No")),
|
||||
],
|
||||
cancelId: 1,
|
||||
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentMainService), product.nameShort),
|
||||
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath, this.environmentMainService), this.productService.nameShort),
|
||||
detail: localize('confirmOpenDetail', "If you did not initiate this request, it may represent an attempted attack on your system. Unless you took an explicit action to initiate this request, you should press 'No'"),
|
||||
noLink: true
|
||||
});
|
||||
@@ -948,16 +954,22 @@ export class CodeApplication extends Disposable {
|
||||
type SharedProcessErrorClassification = {
|
||||
type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
reason: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
visible: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
};
|
||||
type SharedProcessErrorEvent = {
|
||||
type: WindowError;
|
||||
reason: string | undefined;
|
||||
visible: boolean;
|
||||
};
|
||||
telemetryService.publicLog2<SharedProcessErrorEvent, SharedProcessErrorClassification>('sharedprocesserror', { type, reason: typeof details !== 'string' ? details.reason : undefined });
|
||||
telemetryService.publicLog2<SharedProcessErrorEvent, SharedProcessErrorClassification>('sharedprocesserror', {
|
||||
type,
|
||||
reason: typeof details !== 'string' ? details?.reason : undefined,
|
||||
visible: sharedProcess.isVisible()
|
||||
});
|
||||
}));
|
||||
|
||||
// Windows: install mutex
|
||||
const win32MutexName = product.win32MutexName;
|
||||
const win32MutexName = this.productService.win32MutexName;
|
||||
if (isWindows && win32MutexName) {
|
||||
try {
|
||||
const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex;
|
||||
@@ -1027,7 +1039,7 @@ export class CodeApplication extends Disposable {
|
||||
|
||||
recordingStopped = true; // only once
|
||||
|
||||
const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
|
||||
const path = await contentTracing.stopRecording(joinPath(this.environmentMainService.userHome, `${this.productService.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`).fsPath);
|
||||
|
||||
if (!timeout) {
|
||||
dialogMainService.showMessageBox({
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
|
||||
import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService';
|
||||
import { IEncryptionMainService } from 'vs/platform/encryption/electron-main/encryptionMainService';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
interface ElectronAuthenticationResponseDetails extends AuthenticationResponseDetails {
|
||||
@@ -56,7 +56,7 @@ enum ProxyAuthState {
|
||||
|
||||
export class ProxyAuthHandler extends Disposable {
|
||||
|
||||
private static PROXY_CREDENTIALS_SERVICE_KEY = `${product.urlProtocol}.proxy-credentials`;
|
||||
private readonly PROXY_CREDENTIALS_SERVICE_KEY = `${this.productService.urlProtocol}.proxy-credentials`;
|
||||
|
||||
private pendingProxyResolve: Promise<Credentials | undefined> | undefined = undefined;
|
||||
|
||||
@@ -68,7 +68,8 @@ export class ProxyAuthHandler extends Disposable {
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IWindowsMainService private readonly windowsMainService: IWindowsMainService,
|
||||
@INativeHostMainService private readonly nativeHostMainService: INativeHostMainService,
|
||||
@IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService
|
||||
@IEncryptionMainService private readonly encryptionMainService: IEncryptionMainService,
|
||||
@IProductService private readonly productService: IProductService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -153,7 +154,7 @@ export class ProxyAuthHandler extends Disposable {
|
||||
let storedUsername: string | undefined = undefined;
|
||||
let storedPassword: string | undefined = undefined;
|
||||
try {
|
||||
const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
|
||||
const encryptedSerializedProxyCredentials = await this.nativeHostMainService.getPassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
|
||||
if (encryptedSerializedProxyCredentials) {
|
||||
const credentials: Credentials = JSON.parse(await this.encryptionMainService.decrypt(encryptedSerializedProxyCredentials));
|
||||
|
||||
@@ -211,9 +212,9 @@ export class ProxyAuthHandler extends Disposable {
|
||||
try {
|
||||
if (reply.remember) {
|
||||
const encryptedSerializedCredentials = await this.encryptionMainService.encrypt(JSON.stringify(credentials));
|
||||
await this.nativeHostMainService.setPassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials);
|
||||
await this.nativeHostMainService.setPassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash, encryptedSerializedCredentials);
|
||||
} else {
|
||||
await this.nativeHostMainService.deletePassword(undefined, ProxyAuthHandler.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
|
||||
await this.nativeHostMainService.deletePassword(undefined, this.PROXY_CREDENTIALS_SERVICE_KEY, authInfoHash);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logService.error(error); // handle gracefully
|
||||
|
||||
@@ -23,7 +23,6 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { ILogService, ConsoleMainLogger, MultiplexLogService, getLogLevel, ILoggerService } from 'vs/platform/log/common/log';
|
||||
import { StateService } from 'vs/platform/state/node/stateService';
|
||||
import { IStateService } from 'vs/platform/state/node/state';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||
@@ -54,6 +53,7 @@ import { EnvironmentMainService, IEnvironmentMainService } from 'vs/platform/env
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
import { cwd } from 'vs/base/common/process';
|
||||
|
||||
/**
|
||||
* The main VS Code entry point.
|
||||
@@ -84,7 +84,7 @@ class CodeMain {
|
||||
const args = this.resolveArgs();
|
||||
|
||||
// Create services
|
||||
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService] = this.createServices(args);
|
||||
const [instantiationService, instanceEnvironment, environmentService, configurationService, stateService, bufferLogService, productService] = this.createServices(args);
|
||||
|
||||
try {
|
||||
|
||||
@@ -94,7 +94,7 @@ class CodeMain {
|
||||
} catch (error) {
|
||||
|
||||
// Show a dialog for errors that can be resolved by the user
|
||||
this.handleStartupDataDirError(environmentService, error);
|
||||
this.handleStartupDataDirError(environmentService, productService.nameLong, error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ class CodeMain {
|
||||
// Create the main IPC server by trying to be the server
|
||||
// If this throws an error it means we are not the first
|
||||
// instance of VS Code running and so we would quit.
|
||||
const mainProcessNodeIpcServer = await this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, true);
|
||||
const mainProcessNodeIpcServer = await this.doStartup(args, logService, environmentService, lifecycleMainService, instantiationService, productService, true);
|
||||
|
||||
// Delay creation of spdlog for perf reasons (https://github.com/microsoft/vscode/issues/72906)
|
||||
bufferLogService.logger = new SpdLogLogger('main', join(environmentService.logsPath, 'main.log'), true, bufferLogService.getLevel());
|
||||
@@ -126,20 +126,23 @@ class CodeMain {
|
||||
}
|
||||
}
|
||||
|
||||
private createServices(args: NativeParsedArgs): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService] {
|
||||
private createServices(args: NativeParsedArgs): [IInstantiationService, IProcessEnvironment, IEnvironmentMainService, ConfigurationService, StateService, BufferLogService, IProductService] {
|
||||
const services = new ServiceCollection();
|
||||
|
||||
// Product
|
||||
const productService = { _serviceBrand: undefined, ...product };
|
||||
services.set(IProductService, productService);
|
||||
|
||||
// Environment
|
||||
const environmentService = new EnvironmentMainService(args);
|
||||
const instanceEnvironment = this.patchEnvironment(environmentService); // Patch `process.env` with the instance's environment
|
||||
services.set(IEnvironmentService, environmentService);
|
||||
services.set(IEnvironmentMainService, environmentService);
|
||||
const environmentMainService = new EnvironmentMainService(args, productService);
|
||||
const instanceEnvironment = this.patchEnvironment(environmentMainService); // Patch `process.env` with the instance's environment
|
||||
services.set(IEnvironmentMainService, environmentMainService);
|
||||
|
||||
// Log: We need to buffer the spdlog logs until we are sure
|
||||
// we are the only instance running, otherwise we'll have concurrent
|
||||
// log file access on Windows (https://github.com/microsoft/vscode/issues/41218)
|
||||
const bufferLogService = new BufferLogService();
|
||||
const logService = new MultiplexLogService([new ConsoleMainLogger(getLogLevel(environmentService)), bufferLogService]);
|
||||
const logService = new MultiplexLogService([new ConsoleMainLogger(getLogLevel(environmentMainService)), bufferLogService]);
|
||||
process.once('exit', () => logService.dispose());
|
||||
services.set(ILogService, logService);
|
||||
|
||||
@@ -153,14 +156,14 @@ class CodeMain {
|
||||
services.set(ILoggerService, new LoggerService(logService, fileService));
|
||||
|
||||
// Configuration
|
||||
const configurationService = new ConfigurationService(environmentService.settingsResource, fileService);
|
||||
const configurationService = new ConfigurationService(environmentMainService.settingsResource, fileService);
|
||||
services.set(IConfigurationService, configurationService);
|
||||
|
||||
// Lifecycle
|
||||
services.set(ILifecycleMainService, new SyncDescriptor(LifecycleMainService));
|
||||
|
||||
// State
|
||||
const stateService = new StateService(environmentService, logService);
|
||||
const stateService = new StateService(environmentMainService, logService);
|
||||
services.set(IStateService, stateService);
|
||||
|
||||
// Request
|
||||
@@ -172,13 +175,10 @@ class CodeMain {
|
||||
// Signing
|
||||
services.set(ISignService, new SyncDescriptor(SignService));
|
||||
|
||||
// Product
|
||||
services.set(IProductService, { _serviceBrand: undefined, ...product });
|
||||
|
||||
// Tunnel
|
||||
services.set(ITunnelService, new SyncDescriptor(TunnelService));
|
||||
|
||||
return [new InstantiationService(services, true), instanceEnvironment, environmentService, configurationService, stateService, bufferLogService];
|
||||
return [new InstantiationService(services, true), instanceEnvironment, environmentMainService, configurationService, stateService, bufferLogService, productService];
|
||||
}
|
||||
|
||||
private patchEnvironment(environmentMainService: IEnvironmentMainService): IProcessEnvironment {
|
||||
@@ -219,7 +219,7 @@ class CodeMain {
|
||||
return Promise.all([environmentServiceInitialization, configurationServiceInitialization, stateServiceInitialization]);
|
||||
}
|
||||
|
||||
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, retry: boolean): Promise<NodeIPCServer> {
|
||||
private async doStartup(args: NativeParsedArgs, logService: ILogService, environmentMainService: IEnvironmentMainService, lifecycleMainService: ILifecycleMainService, instantiationService: IInstantiationService, productService: IProductService, retry: boolean): Promise<NodeIPCServer> {
|
||||
|
||||
// Try to setup a server for running. If that succeeds it means
|
||||
// we are the first instance to startup. Otherwise it is likely
|
||||
@@ -235,7 +235,7 @@ class CodeMain {
|
||||
if (error.code !== 'EADDRINUSE') {
|
||||
|
||||
// Show a dialog for errors that can be resolved by the user
|
||||
this.handleStartupDataDirError(environmentMainService, error);
|
||||
this.handleStartupDataDirError(environmentMainService, productService.nameLong, error);
|
||||
|
||||
// Any other runtime error is just printed to the console
|
||||
throw error;
|
||||
@@ -251,8 +251,9 @@ class CodeMain {
|
||||
if (!retry || isWindows || error.code !== 'ECONNREFUSED') {
|
||||
if (error.code === 'EPERM') {
|
||||
this.showStartupWarningDialog(
|
||||
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", product.nameShort),
|
||||
localize('secondInstanceAdminDetail', "Please close the other instance and try again.")
|
||||
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", productService.nameShort),
|
||||
localize('secondInstanceAdminDetail', "Please close the other instance and try again."),
|
||||
productService.nameLong
|
||||
);
|
||||
}
|
||||
|
||||
@@ -270,7 +271,7 @@ class CodeMain {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, false);
|
||||
return this.doStartup(args, logService, environmentMainService, lifecycleMainService, instantiationService, productService, false);
|
||||
}
|
||||
|
||||
// Tests from CLI require to be the only instance currently
|
||||
@@ -289,8 +290,9 @@ class CodeMain {
|
||||
if (!args.wait && !args.status) {
|
||||
startupWarningDialogHandle = setTimeout(() => {
|
||||
this.showStartupWarningDialog(
|
||||
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", product.nameShort),
|
||||
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again.")
|
||||
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", productService.nameShort),
|
||||
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again."),
|
||||
productService.nameLong
|
||||
);
|
||||
}, 10000);
|
||||
}
|
||||
@@ -300,7 +302,7 @@ class CodeMain {
|
||||
// Process Info
|
||||
if (args.status) {
|
||||
return instantiationService.invokeFunction(async () => {
|
||||
const diagnosticsService = new DiagnosticsService(NullTelemetryService);
|
||||
const diagnosticsService = new DiagnosticsService(NullTelemetryService, productService);
|
||||
const mainProcessInfo = await launchService.getMainProcessInfo();
|
||||
const remoteDiagnostics = await launchService.getRemoteDiagnostics({ includeProcesses: true, includeWorkspaceMetadata: true });
|
||||
const diagnostics = await diagnosticsService.getDiagnostics(mainProcessInfo, remoteDiagnostics);
|
||||
@@ -344,23 +346,24 @@ class CodeMain {
|
||||
return mainProcessNodeIpcServer;
|
||||
}
|
||||
|
||||
private handleStartupDataDirError(environmentMainService: IEnvironmentMainService, error: NodeJS.ErrnoException): void {
|
||||
private handleStartupDataDirError(environmentMainService: IEnvironmentMainService, title: string, error: NodeJS.ErrnoException): void {
|
||||
if (error.code === 'EACCES' || error.code === 'EPERM') {
|
||||
const directories = coalesce([environmentMainService.userDataPath, environmentMainService.extensionsPath, XDG_RUNTIME_DIR]).map(folder => getPathLabel(folder, environmentMainService));
|
||||
|
||||
this.showStartupWarningDialog(
|
||||
localize('startupDataDirError', "Unable to write program user data."),
|
||||
localize('startupUserDataAndExtensionsDirErrorDetail', "{0}\n\nPlease make sure the following directories are writeable:\n\n{1}", toErrorMessage(error), directories.join('\n'))
|
||||
localize('startupUserDataAndExtensionsDirErrorDetail', "{0}\n\nPlease make sure the following directories are writeable:\n\n{1}", toErrorMessage(error), directories.join('\n')),
|
||||
title
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private showStartupWarningDialog(message: string, detail: string): void {
|
||||
private showStartupWarningDialog(message: string, detail: string, title: string): void {
|
||||
// use sync variant here because we likely exit after this method
|
||||
// due to startup issues and otherwise the dialog seems to disappear
|
||||
// https://github.com/microsoft/vscode/issues/104493
|
||||
dialog.showMessageBoxSync({
|
||||
title: product.nameLong,
|
||||
title,
|
||||
type: 'warning',
|
||||
buttons: [mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
|
||||
message,
|
||||
@@ -451,7 +454,7 @@ class CodeMain {
|
||||
}
|
||||
|
||||
private doValidatePaths(args: string[], gotoLineMode?: boolean): string[] {
|
||||
const cwd = process.env['VSCODE_CWD'] || process.cwd();
|
||||
const currentWorkingDir = cwd();
|
||||
const result = args.map(arg => {
|
||||
let pathCandidate = String(arg);
|
||||
|
||||
@@ -462,10 +465,10 @@ class CodeMain {
|
||||
}
|
||||
|
||||
if (pathCandidate) {
|
||||
pathCandidate = this.preparePath(cwd, pathCandidate);
|
||||
pathCandidate = this.preparePath(currentWorkingDir, pathCandidate);
|
||||
}
|
||||
|
||||
const sanitizedFilePath = sanitizeFilePath(pathCandidate, cwd);
|
||||
const sanitizedFilePath = sanitizeFilePath(pathCandidate, currentWorkingDir);
|
||||
|
||||
const filePathBasename = basename(sanitizedFilePath);
|
||||
if (filePathBasename /* can be empty if code is opened on root */ && !isValidBasename(filePathBasename)) {
|
||||
|
||||
@@ -13,12 +13,14 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { isLinux, isPreferringBrowserCodeLoad } from 'vs/base/common/platform';
|
||||
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
|
||||
import { extname } from 'vs/base/common/resources';
|
||||
|
||||
type ProtocolCallback = { (result: string | Electron.FilePathWithHeaders | { error: number }): void };
|
||||
|
||||
export class FileProtocolHandler extends Disposable {
|
||||
|
||||
private readonly validRoots = TernarySearchTree.forUris<boolean>(() => !isLinux);
|
||||
private readonly validExtensions = new Set(['.png', '.jpg', '.jpeg', '.gif', '.bmp']); // https://github.com/microsoft/vscode/issues/119384
|
||||
|
||||
constructor(
|
||||
@INativeEnvironmentService environmentService: INativeEnvironmentService,
|
||||
@@ -85,14 +87,23 @@ export class FileProtocolHandler extends Disposable {
|
||||
const fileUri = URI.parse(request.url);
|
||||
|
||||
// isPreferringBrowserCodeLoad: false
|
||||
// => ensure the file path is in our expected roots
|
||||
if (!isPreferringBrowserCodeLoad) {
|
||||
|
||||
// first check by validRoots
|
||||
if (this.validRoots.findSubstr(fileUri)) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
}
|
||||
|
||||
// then check by validExtensions
|
||||
if (this.validExtensions.has(extname(fileUri))) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
}
|
||||
|
||||
// finally block to load the resource
|
||||
this.logService.error(`${Schemas.file}: Refused to load resource ${fileUri.fsPath} from ${Schemas.file}: protocol (original URL: ${request.url})`);
|
||||
|
||||
return callback({ error: -3 /* ABORTED */ });
|
||||
@@ -114,14 +125,24 @@ export class FileProtocolHandler extends Disposable {
|
||||
// ensure the root is valid and properly tell Chrome where the
|
||||
// resource is at.
|
||||
const fileUri = FileAccess.asFileUri(uri);
|
||||
|
||||
// first check by validRoots
|
||||
if (this.validRoots.findSubstr(fileUri)) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
} else {
|
||||
this.logService.error(`${Schemas.vscodeFileResource}: Refused to load resource ${fileUri.fsPath} from ${Schemas.vscodeFileResource}: protocol (original URL: ${request.url})`);
|
||||
|
||||
return callback({ error: -3 /* ABORTED */ });
|
||||
}
|
||||
|
||||
// then check by validExtensions
|
||||
if (this.validExtensions.has(extname(fileUri))) {
|
||||
return callback({
|
||||
path: fileUri.fsPath
|
||||
});
|
||||
}
|
||||
|
||||
// finally block to load the resource
|
||||
this.logService.error(`${Schemas.vscodeFileResource}: Refused to load resource ${fileUri.fsPath} from ${Schemas.vscodeFileResource}: protocol (original URL: ${request.url})`);
|
||||
|
||||
return callback({ error: -3 /* ABORTED */ });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,12 @@ interface SearchResult {
|
||||
state?: string;
|
||||
}
|
||||
|
||||
enum IssueSource {
|
||||
VSCode = 'vscode',
|
||||
Extension = 'extension',
|
||||
Marketplace = 'marketplace'
|
||||
}
|
||||
|
||||
export interface IssueReporterConfiguration extends IWindowConfiguration {
|
||||
windowId: number;
|
||||
disableExtensions: boolean;
|
||||
@@ -53,6 +59,7 @@ export interface IssueReporterConfiguration extends IWindowConfiguration {
|
||||
commit: string | undefined;
|
||||
date: string | undefined;
|
||||
reportIssueUrl: string | undefined;
|
||||
reportMarketplaceIssueUrl: string | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,17 +333,18 @@ export class IssueReporter extends Disposable {
|
||||
hide(problemSourceHelpText);
|
||||
}
|
||||
|
||||
const fileOnExtension = JSON.parse(value);
|
||||
this.issueReporterModel.update({ fileOnExtension: fileOnExtension });
|
||||
let fileOnExtension, fileOnMarketplace = false;
|
||||
if (value === IssueSource.Extension) {
|
||||
fileOnExtension = true;
|
||||
} else if (value === IssueSource.Marketplace) {
|
||||
fileOnMarketplace = true;
|
||||
}
|
||||
|
||||
this.issueReporterModel.update({ fileOnExtension, fileOnMarketplace });
|
||||
this.render();
|
||||
|
||||
const title = (<HTMLInputElement>this.getElementById('issue-title')).value;
|
||||
if (fileOnExtension) {
|
||||
this.searchExtensionIssues(title);
|
||||
} else {
|
||||
const description = this.issueReporterModel.getData().issueDescription;
|
||||
this.searchVSCodeIssues(title, description);
|
||||
}
|
||||
this.searchIssues(title, fileOnExtension, fileOnMarketplace);
|
||||
});
|
||||
|
||||
this.addEventListener('description', 'input', (e: Event) => {
|
||||
@@ -353,23 +361,19 @@ export class IssueReporter extends Disposable {
|
||||
this.addEventListener('issue-title', 'input', (e: Event) => {
|
||||
const title = (<HTMLInputElement>e.target).value;
|
||||
const lengthValidationMessage = this.getElementById('issue-title-length-validation-error');
|
||||
if (title && this.getIssueUrlWithTitle(title).length > MAX_URL_LENGTH) {
|
||||
const issueUrl = this.getIssueUrl();
|
||||
if (title && this.getIssueUrlWithTitle(title, issueUrl).length > MAX_URL_LENGTH) {
|
||||
show(lengthValidationMessage);
|
||||
} else {
|
||||
hide(lengthValidationMessage);
|
||||
}
|
||||
|
||||
const fileOnExtension = this.issueReporterModel.fileOnExtension();
|
||||
if (fileOnExtension === undefined) {
|
||||
const issueSource = this.getElementById<HTMLSelectElement>('issue-source');
|
||||
if (!issueSource || issueSource.value === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileOnExtension) {
|
||||
this.searchExtensionIssues(title);
|
||||
} else {
|
||||
const description = this.issueReporterModel.getData().issueDescription;
|
||||
this.searchVSCodeIssues(title, description);
|
||||
}
|
||||
const { fileOnExtension, fileOnMarketplace } = this.issueReporterModel.getData();
|
||||
this.searchIssues(title, fileOnExtension, fileOnMarketplace);
|
||||
});
|
||||
|
||||
this.previewButton.onDidClick(() => this.createIssue());
|
||||
@@ -489,6 +493,19 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private searchIssues(title: string, fileOnExtension: boolean | undefined, fileOnMarketplace: boolean | undefined): void {
|
||||
if (fileOnExtension) {
|
||||
return this.searchExtensionIssues(title);
|
||||
}
|
||||
|
||||
if (fileOnMarketplace) {
|
||||
return this.searchMarketplaceIssues(title);
|
||||
}
|
||||
|
||||
const description = this.issueReporterModel.getData().issueDescription;
|
||||
this.searchVSCodeIssues(title, description);
|
||||
}
|
||||
|
||||
private searchExtensionIssues(title: string): void {
|
||||
const url = this.getExtensionGitHubUrl();
|
||||
if (title) {
|
||||
@@ -509,6 +526,15 @@ export class IssueReporter extends Disposable {
|
||||
this.clearSearchResults();
|
||||
}
|
||||
|
||||
private searchMarketplaceIssues(title: string): void {
|
||||
if (title) {
|
||||
const gitHubInfo = this.parseGitHubUrl(this.configuration.product.reportMarketplaceIssueUrl!);
|
||||
if (gitHubInfo) {
|
||||
return this.searchGitHub(`${gitHubInfo.owner}/${gitHubInfo.repositoryName}`, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private clearSearchResults(): void {
|
||||
const similarIssues = this.getElementById('similar-issues')!;
|
||||
similarIssues.innerText = '';
|
||||
@@ -636,7 +662,7 @@ export class IssueReporter extends Disposable {
|
||||
reset(typeSelect,
|
||||
makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")),
|
||||
makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")),
|
||||
makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue"))
|
||||
makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")),
|
||||
);
|
||||
|
||||
typeSelect.value = issueType.toString();
|
||||
@@ -666,19 +692,15 @@ export class IssueReporter extends Disposable {
|
||||
}
|
||||
|
||||
sourceSelect.innerText = '';
|
||||
if (issueType === IssueType.FeatureRequest) {
|
||||
sourceSelect.append(...[
|
||||
this.makeOption('', localize('selectSource', "Select source"), true),
|
||||
this.makeOption('false', localize('vscode', "Visual Studio Code"), false),
|
||||
this.makeOption('true', localize('extension', "An extension"), false)
|
||||
]);
|
||||
} else {
|
||||
sourceSelect.append(...[
|
||||
this.makeOption('', localize('selectSource', "Select source"), true),
|
||||
this.makeOption('false', localize('vscode', "Visual Studio Code"), false),
|
||||
this.makeOption('true', localize('extension', "An extension"), false),
|
||||
this.makeOption('', localize('unknown', "Don't Know"), false)
|
||||
]);
|
||||
sourceSelect.append(this.makeOption('', localize('selectSource', "Select source"), true));
|
||||
sourceSelect.append(this.makeOption('vscode', localize('vscode', "Visual Studio Code"), false));
|
||||
sourceSelect.append(this.makeOption('extension', localize('extension', "An extension"), false));
|
||||
if (this.configuration.product.reportMarketplaceIssueUrl) {
|
||||
sourceSelect.append(this.makeOption('marketplace', localize('marketplace', "Extensions marketplace"), false));
|
||||
}
|
||||
|
||||
if (issueType !== IssueType.FeatureRequest) {
|
||||
sourceSelect.append(this.makeOption('', localize('unknown', "Don't know"), false));
|
||||
}
|
||||
|
||||
if (selected !== -1 && selected < sourceSelect.options.length) {
|
||||
@@ -691,7 +713,7 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
private renderBlocks(): void {
|
||||
// Depending on Issue Type, we render different blocks and text
|
||||
const { issueType, fileOnExtension } = this.issueReporterModel.getData();
|
||||
const { issueType, fileOnExtension, fileOnMarketplace } = this.issueReporterModel.getData();
|
||||
const blockContainer = this.getElementById('block-container');
|
||||
const systemBlock = document.querySelector('.block-system');
|
||||
const processBlock = document.querySelector('.block-process');
|
||||
@@ -715,29 +737,35 @@ export class IssueReporter extends Disposable {
|
||||
hide(extensionSelector);
|
||||
|
||||
if (issueType === IssueType.Bug) {
|
||||
show(blockContainer);
|
||||
show(systemBlock);
|
||||
show(problemSource);
|
||||
show(experimentsBlock);
|
||||
|
||||
if (!fileOnMarketplace) {
|
||||
show(blockContainer);
|
||||
show(systemBlock);
|
||||
show(experimentsBlock);
|
||||
}
|
||||
|
||||
if (fileOnExtension) {
|
||||
show(extensionSelector);
|
||||
} else {
|
||||
} else if (!fileOnMarketplace) {
|
||||
show(extensionsBlock);
|
||||
}
|
||||
reset(descriptionTitle, localize('stepsToReproduce', "Steps to Reproduce"), $('span.required-input', undefined, '*'));
|
||||
reset(descriptionSubtitle, localize('bugDescription', "Share the steps needed to reliably reproduce the problem. Please include actual and expected results. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub."));
|
||||
} else if (issueType === IssueType.PerformanceIssue) {
|
||||
show(blockContainer);
|
||||
show(systemBlock);
|
||||
show(processBlock);
|
||||
show(workspaceBlock);
|
||||
show(problemSource);
|
||||
show(experimentsBlock);
|
||||
|
||||
if (!fileOnMarketplace) {
|
||||
show(blockContainer);
|
||||
show(systemBlock);
|
||||
show(processBlock);
|
||||
show(workspaceBlock);
|
||||
show(experimentsBlock);
|
||||
}
|
||||
|
||||
if (fileOnExtension) {
|
||||
show(extensionSelector);
|
||||
} else {
|
||||
} else if (!fileOnMarketplace) {
|
||||
show(extensionsBlock);
|
||||
}
|
||||
|
||||
@@ -845,13 +873,13 @@ export class IssueReporter extends Disposable {
|
||||
const issueTitle = (<HTMLInputElement>this.getElementById('issue-title')).value;
|
||||
const issueBody = this.issueReporterModel.serialize();
|
||||
|
||||
const issueUrl = this.issueReporterModel.fileOnExtension() ? this.getExtensionGitHubUrl() : this.configuration.product.reportIssueUrl!;
|
||||
const issueUrl = this.getIssueUrl();
|
||||
const gitHubDetails = this.parseGitHubUrl(issueUrl);
|
||||
if (this.configuration.data.githubAccessToken && gitHubDetails) {
|
||||
return this.submitToGitHub(issueTitle, issueBody, gitHubDetails);
|
||||
}
|
||||
|
||||
const baseUrl = this.getIssueUrlWithTitle((<HTMLInputElement>this.getElementById('issue-title')).value);
|
||||
const baseUrl = this.getIssueUrlWithTitle((<HTMLInputElement>this.getElementById('issue-title')).value, issueUrl);
|
||||
let url = baseUrl + `&body=${encodeURIComponent(issueBody)}`;
|
||||
|
||||
if (url.length > MAX_URL_LENGTH) {
|
||||
@@ -881,6 +909,14 @@ export class IssueReporter extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private getIssueUrl(): string {
|
||||
return this.issueReporterModel.fileOnExtension()
|
||||
? this.getExtensionGitHubUrl()
|
||||
: this.issueReporterModel.getData().fileOnMarketplace
|
||||
? this.configuration.product.reportMarketplaceIssueUrl!
|
||||
: this.configuration.product.reportIssueUrl!;
|
||||
}
|
||||
|
||||
private parseGitHubUrl(url: string): undefined | { repositoryName: string, owner: string } {
|
||||
// Assumes a GitHub url to a particular repo, https://github.com/repositoryName/owner.
|
||||
// Repository name and owner cannot contain '/'
|
||||
@@ -909,16 +945,12 @@ export class IssueReporter extends Disposable {
|
||||
return repositoryUrl;
|
||||
}
|
||||
|
||||
private getIssueUrlWithTitle(issueTitle: string): string {
|
||||
let repositoryUrl = this.configuration.product.reportIssueUrl;
|
||||
private getIssueUrlWithTitle(issueTitle: string, repositoryUrl: string): string {
|
||||
if (this.issueReporterModel.fileOnExtension()) {
|
||||
const extensionGitHubUrl = this.getExtensionGitHubUrl();
|
||||
if (extensionGitHubUrl) {
|
||||
repositoryUrl = extensionGitHubUrl + '/issues/new';
|
||||
}
|
||||
repositoryUrl = repositoryUrl + '/issues/new';
|
||||
}
|
||||
|
||||
const queryStringPrefix = this.configuration.product.reportIssueUrl && this.configuration.product.reportIssueUrl.indexOf('?') === -1 ? '?' : '&';
|
||||
const queryStringPrefix = repositoryUrl.indexOf('?') === -1 ? '?' : '&';
|
||||
return `${repositoryUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`;
|
||||
}
|
||||
|
||||
@@ -1156,7 +1188,7 @@ export class IssueReporter extends Disposable {
|
||||
),
|
||||
...extensions.map(extension => $('tr', undefined,
|
||||
$('td', undefined, extension.name),
|
||||
$('td', undefined, extension.publisher.substr(0, 3)),
|
||||
$('td', undefined, extension.publisher?.substr(0, 3) ?? 'N/A'),
|
||||
$('td', undefined, extension.version),
|
||||
))
|
||||
);
|
||||
|
||||
@@ -26,6 +26,7 @@ export interface IssueReporterData {
|
||||
enabledNonThemeExtesions?: IssueReporterExtensionData[];
|
||||
extensionsDisabled?: boolean;
|
||||
fileOnExtension?: boolean;
|
||||
fileOnMarketplace?: boolean;
|
||||
selectedExtension?: IssueReporterExtensionData;
|
||||
actualSearchResults?: ISettingSearchResult[];
|
||||
query?: string;
|
||||
@@ -110,30 +111,30 @@ ${this.getInfos()}
|
||||
let info = '';
|
||||
|
||||
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
|
||||
if (this._data.includeSystemInfo && this._data.systemInfo) {
|
||||
if (!this._data.fileOnMarketplace && this._data.includeSystemInfo && this._data.systemInfo) {
|
||||
info += this.generateSystemInfoMd();
|
||||
}
|
||||
}
|
||||
|
||||
if (this._data.issueType === IssueType.PerformanceIssue) {
|
||||
|
||||
if (this._data.includeProcessInfo) {
|
||||
if (!this._data.fileOnMarketplace && this._data.includeProcessInfo) {
|
||||
info += this.generateProcessInfoMd();
|
||||
}
|
||||
|
||||
if (this._data.includeWorkspaceInfo) {
|
||||
if (!this._data.fileOnMarketplace && this._data.includeWorkspaceInfo) {
|
||||
info += this.generateWorkspaceInfoMd();
|
||||
}
|
||||
}
|
||||
|
||||
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
|
||||
if (!this._data.fileOnExtension && this._data.includeExtensions) {
|
||||
if (!this._data.fileOnMarketplace && !this._data.fileOnExtension && this._data.includeExtensions) {
|
||||
info += this.generateExtensionsMd();
|
||||
}
|
||||
}
|
||||
|
||||
if (this._data.issueType === IssueType.Bug || this._data.issueType === IssueType.PerformanceIssue) {
|
||||
if (this._data.includeExperiments && this._data.experimentInfo) {
|
||||
if (!this._data.fileOnMarketplace && this._data.includeExperiments && this._data.experimentInfo) {
|
||||
info += this.generateExperimentsInfoMd();
|
||||
}
|
||||
}
|
||||
@@ -238,7 +239,7 @@ ${this._data.experimentInfo}
|
||||
const tableHeader = `Extension|Author (truncated)|Version
|
||||
---|---|---`;
|
||||
const table = this._data.enabledNonThemeExtesions.map(e => {
|
||||
return `${e.name}|${e.publisher.substr(0, 3)}|${e.version}`;
|
||||
return `${e.name}|${e.publisher?.substr(0, 3) ?? 'N/A'}|${e.version}`;
|
||||
}).join('\n');
|
||||
|
||||
return `<details><summary>Extensions (${this._data.enabledNonThemeExtesions.length})</summary>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { homedir } from 'os';
|
||||
import { constants, existsSync, statSync, unlinkSync, chmodSync, truncateSync, readFileSync } from 'fs';
|
||||
import { existsSync, statSync, unlinkSync, chmodSync, truncateSync, readFileSync } from 'fs';
|
||||
import { spawn, ChildProcess, SpawnOptions } from 'child_process';
|
||||
import { buildHelpMessage, buildVersionMessage, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
@@ -23,7 +23,6 @@ function shouldSpawnCliProcess(argv: NativeParsedArgs): boolean {
|
||||
return !!argv['install-source']
|
||||
|| !!argv['list-extensions']
|
||||
|| !!argv['install-extension']
|
||||
|| !!argv['install-builtin-extension']
|
||||
|| !!argv['uninstall-extension']
|
||||
|| !!argv['locate-extension']
|
||||
|| !!argv['telemetry'];
|
||||
@@ -84,8 +83,8 @@ export async function main(argv: string[]): Promise<any> {
|
||||
let restoreMode = false;
|
||||
if (!!args['file-chmod']) {
|
||||
targetMode = statSync(target).mode;
|
||||
if (!(targetMode & constants.S_IWUSR)) {
|
||||
chmodSync(target, targetMode | constants.S_IWUSR);
|
||||
if (!(targetMode & 0o200 /* File mode indicating writable by owner */)) {
|
||||
chmodSync(target, targetMode | 0o200);
|
||||
restoreMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { IExtensionManagementService, IExtensionGalleryService, IExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
@@ -46,6 +46,7 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza
|
||||
import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { cwd } from 'vs/base/common/process';
|
||||
|
||||
class CliMain extends Disposable {
|
||||
|
||||
@@ -94,9 +95,12 @@ class CliMain extends Disposable {
|
||||
private async initServices(): Promise<[IInstantiationService, AppInsightsAppender[]]> {
|
||||
const services = new ServiceCollection();
|
||||
|
||||
// Product
|
||||
const productService = { _serviceBrand: undefined, ...product };
|
||||
services.set(IProductService, productService);
|
||||
|
||||
// Environment
|
||||
const environmentService = new NativeEnvironmentService(this.argv);
|
||||
services.set(IEnvironmentService, environmentService);
|
||||
const environmentService = new NativeEnvironmentService(this.argv, productService);
|
||||
services.set(INativeEnvironmentService, environmentService);
|
||||
|
||||
// Init folders
|
||||
@@ -131,9 +135,6 @@ class CliMain extends Disposable {
|
||||
const stateService = new StateService(environmentService, logService);
|
||||
services.set(IStateService, stateService);
|
||||
|
||||
// Product
|
||||
services.set(IProductService, { _serviceBrand: undefined, ...product });
|
||||
|
||||
const { appRoot, extensionsPath, extensionDevelopmentLocationURI, isBuilt, installSourcePath } = environmentService;
|
||||
|
||||
// Request
|
||||
@@ -149,15 +150,15 @@ class CliMain extends Disposable {
|
||||
|
||||
// Telemetry
|
||||
const appenders: AppInsightsAppender[] = [];
|
||||
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
|
||||
if (product.aiConfig && product.aiConfig.asimovKey) {
|
||||
appenders.push(new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey));
|
||||
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && productService.enableTelemetry) {
|
||||
if (productService.aiConfig && productService.aiConfig.asimovKey) {
|
||||
appenders.push(new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey));
|
||||
}
|
||||
|
||||
const config: ITelemetryServiceConfig = {
|
||||
appender: combinedAppender(...appenders),
|
||||
sendErrorTelemetry: false,
|
||||
commonProperties: resolveCommonProperties(fileService, release(), process.arch, product.commit, product.version, stateService.getItem('telemetry.machineId'), product.msftInternalDomains, installSourcePath),
|
||||
commonProperties: resolveCommonProperties(fileService, release(), process.arch, productService.commit, productService.version, stateService.getItem('telemetry.machineId'), productService.msftInternalDomains, installSourcePath),
|
||||
piiPaths: [appRoot, extensionsPath]
|
||||
};
|
||||
|
||||
@@ -217,7 +218,7 @@ class CliMain extends Disposable {
|
||||
}
|
||||
|
||||
private asExtensionIdOrVSIX(inputs: string[]): (string | URI)[] {
|
||||
return inputs.map(input => /\.vsix$/i.test(input) ? URI.file(isAbsolute(input) ? input : join(process.cwd(), input)) : input);
|
||||
return inputs.map(input => /\.vsix$/i.test(input) ? URI.file(isAbsolute(input) ? input : join(cwd(), input)) : input);
|
||||
}
|
||||
|
||||
private async setInstallSource(environmentService: INativeEnvironmentService, fileService: IFileService, installSource: string): Promise<void> {
|
||||
|
||||
@@ -7,6 +7,7 @@ import * as nls from 'vs/nls';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { status } from 'vs/base/browser/ui/aria/aria';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Command, EditorCommand, ICommandOptions, registerEditorCommand, MultiCommand, UndoCommand, RedoCommand, SelectAllCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
@@ -280,7 +281,7 @@ abstract class EditorOrNativeTextInputCommand {
|
||||
|
||||
constructor(target: MultiCommand) {
|
||||
// 1. handle case when focus is in editor.
|
||||
target.addImplementation(10000, (accessor: ServicesAccessor, args: any) => {
|
||||
target.addImplementation(10000, 'code-editor', (accessor: ServicesAccessor, args: any) => {
|
||||
// Only if editor text focus (i.e. not if editor has widget focus).
|
||||
const focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
|
||||
if (focusedEditor && focusedEditor.hasTextFocus()) {
|
||||
@@ -290,7 +291,7 @@ abstract class EditorOrNativeTextInputCommand {
|
||||
});
|
||||
|
||||
// 2. handle case when focus is in some other `input` / `textarea`.
|
||||
target.addImplementation(1000, (accessor: ServicesAccessor, args: any) => {
|
||||
target.addImplementation(1000, 'generic-dom-input-textarea', (accessor: ServicesAccessor, args: any) => {
|
||||
// Only if focused on an element that allows for entering text
|
||||
const activeElement = <HTMLElement>document.activeElement;
|
||||
if (activeElement && ['input', 'textarea'].indexOf(activeElement.tagName.toLowerCase()) >= 0) {
|
||||
@@ -301,7 +302,7 @@ abstract class EditorOrNativeTextInputCommand {
|
||||
});
|
||||
|
||||
// 3. (default) handle case when focus is somewhere else.
|
||||
target.addImplementation(0, (accessor: ServicesAccessor, args: any) => {
|
||||
target.addImplementation(0, 'generic-dom', (accessor: ServicesAccessor, args: any) => {
|
||||
// Redirecting to active editor
|
||||
const activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor();
|
||||
if (activeEditor) {
|
||||
@@ -1593,6 +1594,7 @@ export namespace CoreNavigationCommands {
|
||||
]
|
||||
);
|
||||
viewModel.revealPrimaryCursor(args.source, true);
|
||||
status(nls.localize('removedCursor', "Removed secondary cursors"));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1820,7 +1822,7 @@ export namespace CoreEditingCommands {
|
||||
}
|
||||
|
||||
public runCoreEditingCommand(editor: ICodeEditor, viewModel: IViewModel, args: any): void {
|
||||
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(viewModel.getPrevEditOperationType(), viewModel.cursorConfig, viewModel.model, viewModel.getCursorStates().map(s => s.modelState.selection));
|
||||
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(viewModel.getPrevEditOperationType(), viewModel.cursorConfig, viewModel.model, viewModel.getCursorStates().map(s => s.modelState.selection), viewModel.getCursorAutoClosedCharacters());
|
||||
if (shouldPushStackElementBefore) {
|
||||
editor.pushUndoStop();
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
this.textArea.setAttribute('aria-haspopup', 'false');
|
||||
this.textArea.setAttribute('aria-autocomplete', 'both');
|
||||
|
||||
if (platform.isWeb && options.get(EditorOption.readOnly)) {
|
||||
if (options.get(EditorOption.domReadOnly)) {
|
||||
this.textArea.setAttribute('readonly', 'true');
|
||||
}
|
||||
|
||||
@@ -416,9 +416,8 @@ export class TextAreaHandler extends ViewPart {
|
||||
this._accessibilitySupport = options.get(EditorOption.accessibilitySupport);
|
||||
const accessibilityPageSize = options.get(EditorOption.accessibilityPageSize);
|
||||
if (this._accessibilitySupport === AccessibilitySupport.Enabled && accessibilityPageSize === EditorOptions.accessibilityPageSize.defaultValue) {
|
||||
// If a screen reader is attached and the default value is not set we shuold automatically increase the page size to 100 for a better experience
|
||||
// If we put more than 100 lines the nvda can not handle this https://github.com/microsoft/vscode/issues/89717
|
||||
this._accessibilityPageSize = 100;
|
||||
// If a screen reader is attached and the default value is not set we shuold automatically increase the page size to 1000 for a better experience
|
||||
this._accessibilityPageSize = 1000;
|
||||
} else {
|
||||
this._accessibilityPageSize = accessibilityPageSize;
|
||||
}
|
||||
@@ -441,8 +440,8 @@ export class TextAreaHandler extends ViewPart {
|
||||
this.textArea.setAttribute('aria-label', this._getAriaLabel(options));
|
||||
this.textArea.setAttribute('tabindex', String(options.get(EditorOption.tabIndex)));
|
||||
|
||||
if (platform.isWeb && e.hasChanged(EditorOption.readOnly)) {
|
||||
if (options.get(EditorOption.readOnly)) {
|
||||
if (e.hasChanged(EditorOption.domReadOnly)) {
|
||||
if (options.get(EditorOption.domReadOnly)) {
|
||||
this.textArea.setAttribute('readonly', 'true');
|
||||
} else {
|
||||
this.textArea.removeAttribute('readonly');
|
||||
|
||||
@@ -209,26 +209,30 @@ export class TextAreaInput extends Disposable {
|
||||
|
||||
if (
|
||||
platform.isMacintosh
|
||||
&& lastKeyDown
|
||||
&& lastKeyDown.equals(KeyCode.KEY_IN_COMPOSITION)
|
||||
&& this._textAreaState.selectionStart === this._textAreaState.selectionEnd
|
||||
&& this._textAreaState.selectionStart > 0
|
||||
&& this._textAreaState.value.substr(this._textAreaState.selectionStart - 1, 1) === e.data
|
||||
&& (lastKeyDown.code === 'ArrowRight' || lastKeyDown.code === 'ArrowLeft')
|
||||
) {
|
||||
// Handling long press case on macOS + arrow key => pretend the character was selected
|
||||
if (_debugComposition) {
|
||||
console.log(`[compositionstart] Handling long press case on macOS + arrow key`, e);
|
||||
}
|
||||
this._textAreaState = new TextAreaState(
|
||||
this._textAreaState.value,
|
||||
this._textAreaState.selectionStart - 1,
|
||||
this._textAreaState.selectionEnd,
|
||||
this._textAreaState.selectionStartPosition ? new Position(this._textAreaState.selectionStartPosition.lineNumber, this._textAreaState.selectionStartPosition.column - 1) : null,
|
||||
this._textAreaState.selectionEndPosition
|
||||
const isArrowKey = (
|
||||
lastKeyDown && lastKeyDown.equals(KeyCode.KEY_IN_COMPOSITION)
|
||||
&& (lastKeyDown.code === 'ArrowRight' || lastKeyDown.code === 'ArrowLeft')
|
||||
);
|
||||
this._onCompositionStart.fire({ revealDeltaColumns: -1 });
|
||||
return;
|
||||
if (isArrowKey || browser.isFirefox) {
|
||||
// Handling long press case on Chromium/Safari macOS + arrow key => pretend the character was selected
|
||||
// or long press case on Firefox on macOS
|
||||
if (_debugComposition) {
|
||||
console.log(`[compositionstart] Handling long press case on macOS + arrow key or Firefox`, e);
|
||||
}
|
||||
this._textAreaState = new TextAreaState(
|
||||
this._textAreaState.value,
|
||||
this._textAreaState.selectionStart - 1,
|
||||
this._textAreaState.selectionEnd,
|
||||
this._textAreaState.selectionStartPosition ? new Position(this._textAreaState.selectionStartPosition.lineNumber, this._textAreaState.selectionStartPosition.column - 1) : null,
|
||||
this._textAreaState.selectionEndPosition
|
||||
);
|
||||
this._onCompositionStart.fire({ revealDeltaColumns: -1 });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.isAndroid) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import { withNullAsUndefined, assertType } from 'vs/base/common/types';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
|
||||
export type ServicesAccessor = InstantiationServicesAccessor;
|
||||
@@ -149,20 +150,26 @@ export abstract class Command {
|
||||
*/
|
||||
export type CommandImplementation = (accessor: ServicesAccessor, args: unknown) => boolean | Promise<void>;
|
||||
|
||||
interface ICommandImplementationRegistration {
|
||||
priority: number;
|
||||
name: string;
|
||||
implementation: CommandImplementation;
|
||||
}
|
||||
|
||||
export class MultiCommand extends Command {
|
||||
|
||||
private readonly _implementations: [number, CommandImplementation][] = [];
|
||||
private readonly _implementations: ICommandImplementationRegistration[] = [];
|
||||
|
||||
/**
|
||||
* A higher priority gets to be looked at first
|
||||
*/
|
||||
public addImplementation(priority: number, implementation: CommandImplementation): IDisposable {
|
||||
this._implementations.push([priority, implementation]);
|
||||
this._implementations.sort((a, b) => b[0] - a[0]);
|
||||
public addImplementation(priority: number, name: string, implementation: CommandImplementation): IDisposable {
|
||||
this._implementations.push({ priority, name, implementation });
|
||||
this._implementations.sort((a, b) => b.priority - a.priority);
|
||||
return {
|
||||
dispose: () => {
|
||||
for (let i = 0; i < this._implementations.length; i++) {
|
||||
if (this._implementations[i][1] === implementation) {
|
||||
if (this._implementations[i].implementation === implementation) {
|
||||
this._implementations.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
@@ -172,9 +179,11 @@ export class MultiCommand extends Command {
|
||||
}
|
||||
|
||||
public runCommand(accessor: ServicesAccessor, args: any): void | Promise<void> {
|
||||
const logService = accessor.get(ILogService);
|
||||
for (const impl of this._implementations) {
|
||||
const result = impl[1](accessor, args);
|
||||
const result = impl.implementation(accessor, args);
|
||||
if (result) {
|
||||
logService.trace(`Command '${this.id}' was handled by '${impl.name}'.`);
|
||||
if (typeof result === 'boolean') {
|
||||
return;
|
||||
}
|
||||
@@ -339,13 +348,13 @@ export abstract class EditorAction extends EditorCommand {
|
||||
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void>;
|
||||
}
|
||||
|
||||
export abstract class MultiEditorAction extends EditorAction {
|
||||
export class MultiEditorAction extends EditorAction {
|
||||
|
||||
private readonly _implementations: [number, CommandImplementation][] = [];
|
||||
|
||||
constructor(opts: IActionOptions) {
|
||||
super(opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* A higher priority gets to be looked at first
|
||||
*/
|
||||
public addImplementation(priority: number, implementation: CommandImplementation): IDisposable {
|
||||
this._implementations.push([priority, implementation]);
|
||||
this._implementations.sort((a, b) => b[0] - a[0]);
|
||||
@@ -361,20 +370,18 @@ export abstract class MultiEditorAction extends EditorAction {
|
||||
};
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
|
||||
this.reportTelemetry(accessor, editor);
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
|
||||
for (const impl of this._implementations) {
|
||||
if (impl[1](accessor, args)) {
|
||||
return;
|
||||
const result = impl[1](accessor, args);
|
||||
if (result) {
|
||||
if (typeof result === 'boolean') {
|
||||
return;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return this.run(accessor, editor, args || {});
|
||||
}
|
||||
|
||||
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void>;
|
||||
|
||||
}
|
||||
|
||||
//#endregion EditorAction
|
||||
|
||||
@@ -88,7 +88,10 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService {
|
||||
private readonly _editorStyleSheets = new Map<string, RefCountedStyleSheet>();
|
||||
private readonly _themeService: IThemeService;
|
||||
|
||||
constructor(@IThemeService themeService: IThemeService, styleSheet: GlobalStyleSheet | null = null) {
|
||||
constructor(
|
||||
styleSheet: GlobalStyleSheet | null,
|
||||
@IThemeService themeService: IThemeService,
|
||||
) {
|
||||
super();
|
||||
this._globalStyleSheet = styleSheet ? styleSheet : null;
|
||||
this._themeService = themeService;
|
||||
@@ -328,7 +331,7 @@ export class DecorationTypeOptionsProvider implements IModelDecorationOptionsPro
|
||||
}
|
||||
|
||||
|
||||
const _CSS_MAP: { [prop: string]: string; } = {
|
||||
export const _CSS_MAP: { [prop: string]: string; } = {
|
||||
color: 'color:{0} !important;',
|
||||
opacity: 'opacity:{0};',
|
||||
backgroundColor: 'background-color:{0};',
|
||||
|
||||
@@ -166,7 +166,7 @@ export class OpenerService implements IOpenerService {
|
||||
// check with contributed validators
|
||||
const targetURI = typeof target === 'string' ? URI.parse(target) : target;
|
||||
// validate against the original URI that this URI resolves to, if one exists
|
||||
const validationTarget = this._resolvedUriTargets.get(targetURI) ?? targetURI;
|
||||
const validationTarget = this._resolvedUriTargets.get(targetURI) ?? target;
|
||||
for (const validator of this._validators) {
|
||||
if (!(await validator.shouldOpen(validationTarget))) {
|
||||
return false;
|
||||
|
||||
@@ -106,7 +106,7 @@ export class View extends ViewEventHandler {
|
||||
|
||||
// The view context is passed on to most classes (basically to reduce param. counts in ctors)
|
||||
this._context = new ViewContext(configuration, themeService.getColorTheme(), model);
|
||||
this._configPixelRatio = this._configPixelRatio = this._context.configuration.options.get(EditorOption.pixelRatio);
|
||||
this._configPixelRatio = this._context.configuration.options.get(EditorOption.pixelRatio);
|
||||
|
||||
// Ensure the view is the first event handler in order to update the layout
|
||||
this._context.addEventHandler(this);
|
||||
|
||||
@@ -121,9 +121,9 @@ export class RangeUtil {
|
||||
startChildIndex = Math.min(max, Math.max(min, startChildIndex));
|
||||
endChildIndex = Math.min(max, Math.max(min, endChildIndex));
|
||||
|
||||
if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0) {
|
||||
if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0 && !domNode.children[startChildIndex].firstChild) {
|
||||
// We must find the position at the beginning of a <span>
|
||||
// To cover cases of empty <span>s, aboid using a range and use the <span>'s bounding box
|
||||
// To cover cases of empty <span>s, avoid using a range and use the <span>'s bounding box
|
||||
const clientRects = domNode.children[startChildIndex].getClientRects();
|
||||
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft);
|
||||
}
|
||||
|
||||
@@ -509,7 +509,7 @@ const editorConfiguration: IConfigurationNode = {
|
||||
nls.localize('wordBasedSuggestionsMode.matchingDocuments', 'Suggest words from all open documents of the same language.'),
|
||||
nls.localize('wordBasedSuggestionsMode.allDocuments', 'Suggest words from all open documents.')
|
||||
],
|
||||
description: nls.localize('wordBasedSuggestionsMode', "Controls from what documents word based completions are computed.")
|
||||
description: nls.localize('wordBasedSuggestionsMode', "Controls from which documents word based completions are computed.")
|
||||
},
|
||||
'editor.semanticHighlighting.enabled': {
|
||||
enum: [true, false, 'configuredByTheme'],
|
||||
|
||||
@@ -28,7 +28,7 @@ export type EditorAutoSurroundStrategy = 'languageDefined' | 'quotes' | 'bracket
|
||||
/**
|
||||
* Configuration options for typing over closing quotes or brackets
|
||||
*/
|
||||
export type EditorAutoClosingOvertypeStrategy = 'always' | 'auto' | 'never';
|
||||
export type EditorAutoClosingEditStrategy = 'always' | 'auto' | 'never';
|
||||
|
||||
/**
|
||||
* Configuration options for auto indentation in the editor
|
||||
@@ -139,10 +139,15 @@ export interface IEditorOptions {
|
||||
*/
|
||||
extraEditorClassName?: string;
|
||||
/**
|
||||
* Should the editor be read only.
|
||||
* Should the editor be read only. See also `domReadOnly`.
|
||||
* Defaults to false.
|
||||
*/
|
||||
readOnly?: boolean;
|
||||
/**
|
||||
* Should the textarea used for input use the DOM `readonly` attribute.
|
||||
* Defaults to false.
|
||||
*/
|
||||
domReadOnly?: boolean;
|
||||
/**
|
||||
* Enable linked editing.
|
||||
* Defaults to false.
|
||||
@@ -413,10 +418,14 @@ export interface IEditorOptions {
|
||||
* Defaults to language defined behavior.
|
||||
*/
|
||||
autoClosingQuotes?: EditorAutoClosingStrategy;
|
||||
/**
|
||||
* Options for pressing backspace near quotes or bracket pairs.
|
||||
*/
|
||||
autoClosingDelete?: EditorAutoClosingEditStrategy;
|
||||
/**
|
||||
* Options for typing over closing quotes or brackets.
|
||||
*/
|
||||
autoClosingOvertype?: EditorAutoClosingOvertypeStrategy;
|
||||
autoClosingOvertype?: EditorAutoClosingEditStrategy;
|
||||
/**
|
||||
* Options for auto surrounding.
|
||||
* Defaults to always allowing auto surrounding.
|
||||
@@ -1393,8 +1402,8 @@ class EditorFind extends BaseEditorOption<EditorOption.find, EditorFindOptions>
|
||||
enum: ['never', 'always', 'multiline'],
|
||||
default: defaults.autoFindInSelection,
|
||||
enumDescriptions: [
|
||||
nls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in selection automatically (default)'),
|
||||
nls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in selection automatically'),
|
||||
nls.localize('editor.find.autoFindInSelection.never', 'Never turn on Find in selection automatically (default).'),
|
||||
nls.localize('editor.find.autoFindInSelection.always', 'Always turn on Find in selection automatically.'),
|
||||
nls.localize('editor.find.autoFindInSelection.multiline', 'Turn on Find in selection automatically when multiple lines of content are selected.')
|
||||
],
|
||||
description: nls.localize('find.autoFindInSelection', "Controls the condition for turning on find in selection automatically.")
|
||||
@@ -3140,7 +3149,7 @@ export interface ISuggestOptions {
|
||||
*/
|
||||
snippetsPreventQuickSuggestions?: boolean;
|
||||
/**
|
||||
* Favours words that appear close to the cursor.
|
||||
* Favors words that appear close to the cursor.
|
||||
*/
|
||||
localityBonus?: boolean;
|
||||
/**
|
||||
@@ -3332,7 +3341,7 @@ class EditorSuggest extends BaseEditorOption<EditorOption.suggest, InternalSugge
|
||||
'editor.suggest.localityBonus': {
|
||||
type: 'boolean',
|
||||
default: defaults.localityBonus,
|
||||
description: nls.localize('suggest.localityBonus', "Controls whether sorting favours words that appear close to the cursor.")
|
||||
description: nls.localize('suggest.localityBonus', "Controls whether sorting favors words that appear close to the cursor.")
|
||||
},
|
||||
'editor.suggest.shareSuggestSelections': {
|
||||
type: 'boolean',
|
||||
@@ -3725,6 +3734,7 @@ export const enum EditorOption {
|
||||
accessibilityPageSize,
|
||||
ariaLabel,
|
||||
autoClosingBrackets,
|
||||
autoClosingDelete,
|
||||
autoClosingOvertype,
|
||||
autoClosingQuotes,
|
||||
autoIndent,
|
||||
@@ -3746,6 +3756,7 @@ export const enum EditorOption {
|
||||
cursorWidth,
|
||||
disableLayerHinting,
|
||||
disableMonospaceOptimizations,
|
||||
domReadOnly,
|
||||
dragAndDrop,
|
||||
emptySelectionClipboard,
|
||||
extraEditorClassName,
|
||||
@@ -3883,7 +3894,10 @@ export const EditorOptions = {
|
||||
)),
|
||||
accessibilitySupport: register(new EditorAccessibilitySupport()),
|
||||
accessibilityPageSize: register(new EditorIntOption(EditorOption.accessibilityPageSize, 'accessibilityPageSize', 10, 1, Constants.MAX_SAFE_SMALL_INTEGER,
|
||||
{ description: nls.localize('accessibilityPageSize', "Controls the number of lines in the editor that can be read out by a screen reader. Warning: this has a performance implication for numbers larger than the default.") })),
|
||||
{
|
||||
description: nls.localize('accessibilityPageSize', "Controls the number of lines in the editor that can be read out by a screen reader at once. When we detect a screen reader we automatically set the default to be 2000. Warning: this has a performance implication for numbers larger than the default."),
|
||||
deprecationMessage: nls.localize('accessibilityPageSize.deprecated', "This setting is deprecated, editor will automatically choose the accessibility page size when we detect a screen reader. 2000 lines will be the new default.")
|
||||
})),
|
||||
ariaLabel: register(new EditorStringOption(
|
||||
EditorOption.ariaLabel, 'ariaLabel', nls.localize('editorViewAccessibleLabel', "Editor content")
|
||||
)),
|
||||
@@ -3901,6 +3915,19 @@ export const EditorOptions = {
|
||||
description: nls.localize('autoClosingBrackets', "Controls whether the editor should automatically close brackets after the user adds an opening bracket.")
|
||||
}
|
||||
)),
|
||||
autoClosingDelete: register(new EditorStringEnumOption(
|
||||
EditorOption.autoClosingDelete, 'autoClosingDelete',
|
||||
'auto' as 'always' | 'auto' | 'never',
|
||||
['always', 'auto', 'never'] as const,
|
||||
{
|
||||
enumDescriptions: [
|
||||
'',
|
||||
nls.localize('editor.autoClosingDelete.auto', "Remove adjacent closing quotes or brackets only if they were automatically inserted."),
|
||||
'',
|
||||
],
|
||||
description: nls.localize('autoClosingDelete', "Controls whether the editor should remove adjacent closing quotes or brackets when deleting.")
|
||||
}
|
||||
)),
|
||||
autoClosingOvertype: register(new EditorStringEnumOption(
|
||||
EditorOption.autoClosingOvertype, 'autoClosingOvertype',
|
||||
'auto' as 'always' | 'auto' | 'never',
|
||||
@@ -3963,7 +3990,7 @@ export const EditorOptions = {
|
||||
)),
|
||||
stickyTabStops: register(new EditorBooleanOption(
|
||||
EditorOption.stickyTabStops, 'stickyTabStops', false,
|
||||
{ description: nls.localize('stickyTabStops', "Emulate selection behaviour of tab characters when using spaces for indentation. Selection will stick to tab stops.") }
|
||||
{ description: nls.localize('stickyTabStops', "Emulate selection behavior of tab characters when using spaces for indentation. Selection will stick to tab stops.") }
|
||||
)),
|
||||
codeLens: register(new EditorBooleanOption(
|
||||
EditorOption.codeLens, 'codeLens', true,
|
||||
@@ -4042,6 +4069,9 @@ export const EditorOptions = {
|
||||
disableMonospaceOptimizations: register(new EditorBooleanOption(
|
||||
EditorOption.disableMonospaceOptimizations, 'disableMonospaceOptimizations', false
|
||||
)),
|
||||
domReadOnly: register(new EditorBooleanOption(
|
||||
EditorOption.domReadOnly, 'domReadOnly', false,
|
||||
)),
|
||||
dragAndDrop: register(new EditorBooleanOption(
|
||||
EditorOption.dragAndDrop, 'dragAndDrop', true,
|
||||
{ description: nls.localize('dragAndDrop', "Controls whether the editor should allow moving selections via drag and drop.") }
|
||||
@@ -4264,7 +4294,7 @@ export const EditorOptions = {
|
||||
)),
|
||||
renderLineHighlightOnlyWhenFocus: register(new EditorBooleanOption(
|
||||
EditorOption.renderLineHighlightOnlyWhenFocus, 'renderLineHighlightOnlyWhenFocus', false,
|
||||
{ description: nls.localize('renderLineHighlightOnlyWhenFocus', "Controls if the editor should render the current line highlight only when the editor is focused") }
|
||||
{ description: nls.localize('renderLineHighlightOnlyWhenFocus', "Controls if the editor should render the current line highlight only when the editor is focused.") }
|
||||
)),
|
||||
renderValidationDecorations: register(new EditorStringEnumOption(
|
||||
EditorOption.renderValidationDecorations, 'renderValidationDecorations',
|
||||
@@ -4280,7 +4310,7 @@ export const EditorOptions = {
|
||||
'',
|
||||
nls.localize('renderWhitespace.boundary', "Render whitespace characters except for single spaces between words."),
|
||||
nls.localize('renderWhitespace.selection', "Render whitespace characters only on selected text."),
|
||||
nls.localize('renderWhitespace.trailing', "Render only trailing whitespace characters"),
|
||||
nls.localize('renderWhitespace.trailing', "Render only trailing whitespace characters."),
|
||||
''
|
||||
],
|
||||
description: nls.localize('renderWhitespace', "Controls how the editor should render whitespace characters.")
|
||||
|
||||
@@ -620,6 +620,10 @@ export class Cursor extends Disposable {
|
||||
this._isDoingComposition = isDoingComposition;
|
||||
}
|
||||
|
||||
public getAutoClosedCharacters(): Range[] {
|
||||
return AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);
|
||||
}
|
||||
|
||||
public startComposition(eventsCollector: ViewModelEventsCollector): void {
|
||||
this._selectionsWhenCompositionStarted = this.getSelections().slice(0);
|
||||
}
|
||||
@@ -628,8 +632,7 @@ export class Cursor extends Disposable {
|
||||
this._executeEdit(() => {
|
||||
if (source === 'keyboard') {
|
||||
// composition finishes, let's check if we need to auto complete if necessary.
|
||||
const autoClosedCharacters = AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);
|
||||
this._executeEditOperation(TypeOperations.compositionEndWithInterceptors(this._prevEditOperationType, this.context.cursorConfig, this._model, this._selectionsWhenCompositionStarted, this.getSelections(), autoClosedCharacters));
|
||||
this._executeEditOperation(TypeOperations.compositionEndWithInterceptors(this._prevEditOperationType, this.context.cursorConfig, this._model, this._selectionsWhenCompositionStarted, this.getSelections(), this.getAutoClosedCharacters()));
|
||||
this._selectionsWhenCompositionStarted = null;
|
||||
}
|
||||
}, eventsCollector, source);
|
||||
@@ -647,8 +650,7 @@ export class Cursor extends Disposable {
|
||||
const chr = text.substr(offset, charLength);
|
||||
|
||||
// Here we must interpret each typed character individually
|
||||
const autoClosedCharacters = AutoClosedAction.getAllAutoClosedCharacters(this._autoClosedActions);
|
||||
this._executeEditOperation(TypeOperations.typeWithInterceptors(this._isDoingComposition, this._prevEditOperationType, this.context.cursorConfig, this._model, this.getSelections(), autoClosedCharacters, chr));
|
||||
this._executeEditOperation(TypeOperations.typeWithInterceptors(this._isDoingComposition, this._prevEditOperationType, this.context.cursorConfig, this._model, this.getSelections(), this.getAutoClosedCharacters(), chr));
|
||||
|
||||
offset += charLength;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ export class ColumnSelection {
|
||||
|
||||
public static columnSelectLeft(config: CursorConfiguration, model: ICursorSimpleModel, prevColumnSelectData: IColumnSelectData): IColumnSelectResult {
|
||||
let toViewVisualColumn = prevColumnSelectData.toViewVisualColumn;
|
||||
if (toViewVisualColumn > 1) {
|
||||
if (toViewVisualColumn > 0) {
|
||||
toViewVisualColumn--;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, ConfigurationChangedEvent, EditorAutoClosingOvertypeStrategy, EditorOption, EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditorAutoClosingStrategy, EditorAutoSurroundStrategy, ConfigurationChangedEvent, EditorAutoClosingEditStrategy, EditorOption, EditorAutoIndentStrategy } from 'vs/editor/common/config/editorOptions';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { ISelection, Selection } from 'vs/editor/common/core/selection';
|
||||
@@ -73,7 +73,8 @@ export class CursorConfiguration {
|
||||
public readonly multiCursorPaste: 'spread' | 'full';
|
||||
public readonly autoClosingBrackets: EditorAutoClosingStrategy;
|
||||
public readonly autoClosingQuotes: EditorAutoClosingStrategy;
|
||||
public readonly autoClosingOvertype: EditorAutoClosingOvertypeStrategy;
|
||||
public readonly autoClosingDelete: EditorAutoClosingEditStrategy;
|
||||
public readonly autoClosingOvertype: EditorAutoClosingEditStrategy;
|
||||
public readonly autoSurround: EditorAutoSurroundStrategy;
|
||||
public readonly autoIndent: EditorAutoIndentStrategy;
|
||||
public readonly autoClosingPairs: AutoClosingPairs;
|
||||
@@ -92,6 +93,7 @@ export class CursorConfiguration {
|
||||
|| e.hasChanged(EditorOption.multiCursorPaste)
|
||||
|| e.hasChanged(EditorOption.autoClosingBrackets)
|
||||
|| e.hasChanged(EditorOption.autoClosingQuotes)
|
||||
|| e.hasChanged(EditorOption.autoClosingDelete)
|
||||
|| e.hasChanged(EditorOption.autoClosingOvertype)
|
||||
|| e.hasChanged(EditorOption.autoSurround)
|
||||
|| e.hasChanged(EditorOption.useTabStops)
|
||||
@@ -125,6 +127,7 @@ export class CursorConfiguration {
|
||||
this.multiCursorPaste = options.get(EditorOption.multiCursorPaste);
|
||||
this.autoClosingBrackets = options.get(EditorOption.autoClosingBrackets);
|
||||
this.autoClosingQuotes = options.get(EditorOption.autoClosingQuotes);
|
||||
this.autoClosingDelete = options.get(EditorOption.autoClosingDelete);
|
||||
this.autoClosingOvertype = options.get(EditorOption.autoClosingOvertype);
|
||||
this.autoSurround = options.get(EditorOption.autoSurround);
|
||||
this.autoIndent = options.get(EditorOption.autoIndent);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand';
|
||||
import { EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditorAutoClosingEditStrategy, EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
|
||||
import { CursorColumns, CursorConfiguration, EditOperationResult, EditOperationType, ICursorSimpleModel, isQuote } from 'vs/editor/common/controller/cursorCommon';
|
||||
import { MoveOperations } from 'vs/editor/common/controller/cursorMoveOperations';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
@@ -50,15 +50,20 @@ export class DeleteOperations {
|
||||
}
|
||||
|
||||
public static isAutoClosingPairDelete(
|
||||
autoClosingDelete: EditorAutoClosingEditStrategy,
|
||||
autoClosingBrackets: EditorAutoClosingStrategy,
|
||||
autoClosingQuotes: EditorAutoClosingStrategy,
|
||||
autoClosingPairsOpen: Map<string, StandardAutoClosingPairConditional[]>,
|
||||
model: ICursorSimpleModel,
|
||||
selections: Selection[]
|
||||
selections: Selection[],
|
||||
autoClosedCharacters: Range[]
|
||||
): boolean {
|
||||
if (autoClosingBrackets === 'never' && autoClosingQuotes === 'never') {
|
||||
return false;
|
||||
}
|
||||
if (autoClosingDelete === 'never') {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
const selection = selections[i];
|
||||
@@ -100,6 +105,21 @@ export class DeleteOperations {
|
||||
if (!foundAutoClosingPair) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must delete the pair only if it was automatically inserted by the editor
|
||||
if (autoClosingDelete === 'auto') {
|
||||
let found = false;
|
||||
for (let j = 0, lenJ = autoClosedCharacters.length; j < lenJ; j++) {
|
||||
const autoClosedCharacter = autoClosedCharacters[j];
|
||||
if (position.lineNumber === autoClosedCharacter.startLineNumber && position.column === autoClosedCharacter.startColumn) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -120,9 +140,9 @@ export class DeleteOperations {
|
||||
return [true, commands];
|
||||
}
|
||||
|
||||
public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, Array<ICommand | null>] {
|
||||
public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[], autoClosedCharacters: Range[]): [boolean, Array<ICommand | null>] {
|
||||
|
||||
if (this.isAutoClosingPairDelete(config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairs.autoClosingPairsOpenByEnd, model, selections)) {
|
||||
if (this.isAutoClosingPairDelete(config.autoClosingDelete, config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairs.autoClosingPairsOpenByEnd, model, selections, autoClosedCharacters)) {
|
||||
return this._runAutoClosingPairDelete(config, model, selections);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditorAutoClosingEditStrategy, EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
|
||||
import { CursorConfiguration, ICursorSimpleModel, SingleCursorState } from 'vs/editor/common/controller/cursorCommon';
|
||||
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
|
||||
import { WordCharacterClass, WordCharacterClassifier, getMapForWordSeparators } from 'vs/editor/common/controller/wordCharacterClassifier';
|
||||
@@ -52,9 +52,11 @@ export interface DeleteWordContext {
|
||||
model: ITextModel;
|
||||
selection: Selection;
|
||||
whitespaceHeuristics: boolean;
|
||||
autoClosingDelete: EditorAutoClosingEditStrategy;
|
||||
autoClosingBrackets: EditorAutoClosingStrategy;
|
||||
autoClosingQuotes: EditorAutoClosingStrategy;
|
||||
autoClosingPairs: AutoClosingPairs;
|
||||
autoClosedCharacters: Range[];
|
||||
}
|
||||
|
||||
export class WordOperations {
|
||||
@@ -384,7 +386,7 @@ export class WordOperations {
|
||||
return selection;
|
||||
}
|
||||
|
||||
if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection])) {
|
||||
if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingDelete, ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpenByEnd, ctx.model, [ctx.selection], ctx.autoClosedCharacters)) {
|
||||
const position = ctx.selection.getPosition();
|
||||
return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1);
|
||||
}
|
||||
|
||||
@@ -23,10 +23,26 @@ export interface IStringBuilder {
|
||||
appendASCIIString(str: string): void;
|
||||
}
|
||||
|
||||
let _utf16LE_TextDecoder: TextDecoder | null;
|
||||
function getUTF16LE_TextDecoder(): TextDecoder {
|
||||
if (!_utf16LE_TextDecoder) {
|
||||
_utf16LE_TextDecoder = new TextDecoder('UTF-16LE');
|
||||
}
|
||||
return _utf16LE_TextDecoder;
|
||||
}
|
||||
|
||||
let _utf16BE_TextDecoder: TextDecoder | null;
|
||||
function getUTF16BE_TextDecoder(): TextDecoder {
|
||||
if (!_utf16BE_TextDecoder) {
|
||||
_utf16BE_TextDecoder = new TextDecoder('UTF-16BE');
|
||||
}
|
||||
return _utf16BE_TextDecoder;
|
||||
}
|
||||
|
||||
let _platformTextDecoder: TextDecoder | null;
|
||||
export function getPlatformTextDecoder(): TextDecoder {
|
||||
if (!_platformTextDecoder) {
|
||||
_platformTextDecoder = new TextDecoder(platform.isLittleEndian() ? 'UTF-16LE' : 'UTF-16BE');
|
||||
_platformTextDecoder = platform.isLittleEndian() ? getUTF16LE_TextDecoder() : getUTF16BE_TextDecoder();
|
||||
}
|
||||
return _platformTextDecoder;
|
||||
}
|
||||
@@ -45,7 +61,14 @@ if (hasTextDecoder) {
|
||||
|
||||
function standardDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string {
|
||||
const view = new Uint16Array(source.buffer, offset, len);
|
||||
return getPlatformTextDecoder().decode(view);
|
||||
if (len > 0 && (view[0] === 0xFEFF || view[0] === 0xFFFE)) {
|
||||
// UTF16 sometimes starts with a BOM https://de.wikipedia.org/wiki/Byte_Order_Mark
|
||||
// It looks like TextDecoder.decode will eat up a leading BOM (0xFEFF or 0xFFFE)
|
||||
// We don't want that behavior because we know the string is UTF16LE and the BOM should be maintained
|
||||
// So we use the manual decoder
|
||||
return compatDecodeUTF16LE(source, offset, len);
|
||||
}
|
||||
return getUTF16LE_TextDecoder().decode(view);
|
||||
}
|
||||
|
||||
function compatDecodeUTF16LE(source: Uint8Array, offset: number, len: number): string {
|
||||
|
||||
@@ -19,7 +19,7 @@ function uriGetComparisonKey(resource: URI): string {
|
||||
return resource.toString();
|
||||
}
|
||||
|
||||
class SingleModelEditStackData {
|
||||
export class SingleModelEditStackData {
|
||||
|
||||
public static create(model: ITextModel, beforeCursorState: Selection[] | null): SingleModelEditStackData {
|
||||
const alternativeVersionId = model.getAlternativeVersionId();
|
||||
|
||||
@@ -881,55 +881,49 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
* Validates `range` is within buffer bounds, but allows it to sit in between surrogate pairs, etc.
|
||||
* Will try to not allocate if possible.
|
||||
*/
|
||||
private _validateRangeRelaxedNoAllocations(range: IRange): Range {
|
||||
public _validateRangeRelaxedNoAllocations(range: IRange): Range {
|
||||
const linesCount = this._buffer.getLineCount();
|
||||
|
||||
const initialStartLineNumber = range.startLineNumber;
|
||||
const initialStartColumn = range.startColumn;
|
||||
let startLineNumber: number;
|
||||
let startColumn: number;
|
||||
let startLineNumber = Math.floor((typeof initialStartLineNumber === 'number' && !isNaN(initialStartLineNumber)) ? initialStartLineNumber : 1);
|
||||
let startColumn = Math.floor((typeof initialStartColumn === 'number' && !isNaN(initialStartColumn)) ? initialStartColumn : 1);
|
||||
|
||||
if (initialStartLineNumber < 1) {
|
||||
if (startLineNumber < 1) {
|
||||
startLineNumber = 1;
|
||||
startColumn = 1;
|
||||
} else if (initialStartLineNumber > linesCount) {
|
||||
} else if (startLineNumber > linesCount) {
|
||||
startLineNumber = linesCount;
|
||||
startColumn = this.getLineMaxColumn(startLineNumber);
|
||||
} else {
|
||||
startLineNumber = initialStartLineNumber | 0;
|
||||
if (initialStartColumn <= 1) {
|
||||
if (startColumn <= 1) {
|
||||
startColumn = 1;
|
||||
} else {
|
||||
const maxColumn = this.getLineMaxColumn(startLineNumber);
|
||||
if (initialStartColumn >= maxColumn) {
|
||||
if (startColumn >= maxColumn) {
|
||||
startColumn = maxColumn;
|
||||
} else {
|
||||
startColumn = initialStartColumn | 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const initialEndLineNumber = range.endLineNumber;
|
||||
const initialEndColumn = range.endColumn;
|
||||
let endLineNumber: number;
|
||||
let endColumn: number;
|
||||
let endLineNumber = Math.floor((typeof initialEndLineNumber === 'number' && !isNaN(initialEndLineNumber)) ? initialEndLineNumber : 1);
|
||||
let endColumn = Math.floor((typeof initialEndColumn === 'number' && !isNaN(initialEndColumn)) ? initialEndColumn : 1);
|
||||
|
||||
if (initialEndLineNumber < 1) {
|
||||
if (endLineNumber < 1) {
|
||||
endLineNumber = 1;
|
||||
endColumn = 1;
|
||||
} else if (initialEndLineNumber > linesCount) {
|
||||
} else if (endLineNumber > linesCount) {
|
||||
endLineNumber = linesCount;
|
||||
endColumn = this.getLineMaxColumn(endLineNumber);
|
||||
} else {
|
||||
endLineNumber = initialEndLineNumber | 0;
|
||||
if (initialEndColumn <= 1) {
|
||||
if (endColumn <= 1) {
|
||||
endColumn = 1;
|
||||
} else {
|
||||
const maxColumn = this.getLineMaxColumn(endLineNumber);
|
||||
if (initialEndColumn >= maxColumn) {
|
||||
if (endColumn >= maxColumn) {
|
||||
endColumn = maxColumn;
|
||||
} else {
|
||||
endColumn = initialEndColumn | 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,11 +297,11 @@ export interface EvaluatableExpressionProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* An open ended information bag passed to the inline value provider.
|
||||
* A minimal context containes just the document location where the debugger has stopped.
|
||||
* A value-object that contains contextual information when requesting inline values from a InlineValuesProvider.
|
||||
* @internal
|
||||
*/
|
||||
export interface InlineValueContext {
|
||||
frameId: number;
|
||||
stoppedLocation: Range;
|
||||
}
|
||||
|
||||
@@ -699,8 +699,8 @@ export interface CodeAction {
|
||||
* @internal
|
||||
*/
|
||||
export const enum CodeActionTriggerType {
|
||||
Auto = 1,
|
||||
Manual = 2,
|
||||
Invoke = 1,
|
||||
Auto = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1683,33 +1683,6 @@ export interface CommentThreadChangedEvent {
|
||||
readonly changed: CommentThread[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IWebviewPortMapping {
|
||||
webviewPort: number;
|
||||
extensionHostPort: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IWebviewOptions {
|
||||
readonly enableScripts?: boolean;
|
||||
readonly enableCommandUris?: boolean;
|
||||
readonly localResourceRoots?: ReadonlyArray<UriComponents>;
|
||||
readonly portMapping?: ReadonlyArray<IWebviewPortMapping>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IWebviewPanelOptions {
|
||||
readonly enableFindWidget?: boolean;
|
||||
readonly retainContextWhenHidden?: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface CodeLens {
|
||||
range: IRange;
|
||||
id?: string;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { mergeSort } from 'vs/base/common/arrays';
|
||||
import { stringDiff } from 'vs/base/common/diff/diff';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { globals } from 'vs/base/common/platform';
|
||||
@@ -455,7 +454,7 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable {
|
||||
const result: TextEdit[] = [];
|
||||
let lastEol: EndOfLineSequence | undefined = undefined;
|
||||
|
||||
edits = mergeSort(edits, (a, b) => {
|
||||
edits = edits.slice(0).sort((a, b) => {
|
||||
if (a.range && b.range) {
|
||||
return Range.compareRangesUsingStarts(a.range, b.range);
|
||||
}
|
||||
|
||||
@@ -741,6 +741,19 @@ export class ModelSemanticColoring extends Disposable {
|
||||
this._fetchDocumentSemanticTokens.schedule();
|
||||
}
|
||||
}));
|
||||
this._register(this._model.onDidChangeLanguage(() => {
|
||||
// clear any outstanding state
|
||||
if (this._currentDocumentResponse) {
|
||||
this._currentDocumentResponse.dispose();
|
||||
this._currentDocumentResponse = null;
|
||||
}
|
||||
if (this._currentDocumentRequestCancellationTokenSource) {
|
||||
this._currentDocumentRequestCancellationTokenSource.cancel();
|
||||
this._currentDocumentRequestCancellationTokenSource = null;
|
||||
}
|
||||
this._setDocumentSemanticTokens(null, null, null, []);
|
||||
this._fetchDocumentSemanticTokens.schedule(0);
|
||||
}));
|
||||
const bindDocumentChangeListeners = () => {
|
||||
dispose(this._documentProvidersChangeListeners);
|
||||
this._documentProvidersChangeListeners = [];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user