Squashed 'lib/vscode/' changes from 622cb03f7e0..fd6f3bce670

fd6f3bce670 chore: bump electron@11.3.0 (#118680)
305bf142199 Remove icon from input row in ports view (#118649)
b5af426d34c Properly dispose everything in tunnel view cells (#118546)
f299ec03c2a Fix extra port icon (#118529)
62dbffbfe91 Merge pull request #118177 from microsoft/joh/bump-version
062c67a3210 Merge pull request #118491 from microsoft/env-var-recovery
e11b6a730c9 Fix #117903 (#118492)
e7936a3e885 prevent env var relaunch from extension owned terminals
3be37a725d6 Merge pull request #118438 from microsoft/tyriar/1_54_117990
d461d2fd311 Merge pull request #118265 from microsoft/connor4312/candidate/js-debug-1.54.5
88b4d3f9a4e Merge pull request #118448 from microsoft/tyriar/1_54_118321
c48a57b6988 Merge pull request #118437 from microsoft/tyriar/1_54_117956
d68ab8fc717 Don't force create a terminal on no reconnect
f9e6b352d1c Recover on pty host reconnect
b31f6e1afea Don't force kill ptys on Windows on window exit
bd655647d79 fixes #118214 (#118425)
3a6b7f7cbdc editors - fix mergeAllGroups (#118268) (#118406)
06c5e24837e FileSystemProvider extension: throwing a FileSystemError in readFile does not report to user (#118173)
61feeef2289 Renaming a folder adds it to history (fix #118080) (#118174)
dd74fb1d885 debug: update js-debug
362f7e441ff Pick up TS 4.2.3 (#118261)
6b7199812b4 Don't assume uncompleted category exists (#118250)
21ea885f455 Merge pull request #118167 from microsoft/connor4312/candidate/js-debug-1.54.4
de16aa4bae0 bump version to future 1.54.2
87ff6fb52f1 debug: update js-debug
f30a9b73e8f bump version (#118144)
a25525922cd update distro (#118129)
42e27fe5cdc Merge pull request #117982 from microsoft/roblou/settingsOpenEditor
ac575425edc Ensure EditorOptions subclass is passed to openEditor Fix #117952
911868fa126 refs #117960 (#117976)
62c69b32bf7 Merge pull request #117972 from microsoft/tyriar/r_1_54_remote_reconnect
564f3917935 Fix remote terminal reconnect
e7989863202 fixes #117924 (#117925)
c4d7a739c9b Terminal cannot input (#117915)
5266d3cc7f3 Merge pull request #117898 from microsoft/tyriar/r1_54_remote_reconnect
6f0e457db3f Fix emmet update extensions path issue (#117797)
66c7b551727 Implement shouldPersist for all terminals processes
ae03e39735b Only show `infer return type` refactoring when refactorings are requested (#117800)
e590188f171 fix #117792.
fc7005d93f1 delete comment that is covered by #117088
3dd2d431a01 re #117449. add default color in code.
be9c3901da5 Disable overrides in settings and keybindings (#117770)
ea3f3878887 Fix Forward a Port context menu action
d3b97f07fcf Fix ugly name for Focus on Ports View command Fixes microsoft/vscode-remote-release#4564
c1f5d07efdc Use button instead of + for forwarding a port Fixes #117589
c57c05ea364 fixes #117746
aa9f3842964 more fixes for #115840
909e129d6f5 no explicit call of setFocus/Selection outside of notebook cell list.
554341f99fa re #117725. setfocus uses wrong handle for selections.
3290f9a73ba fix #117725.
3eea629b602 Scope down querying getting started service to only cases where it'd affect the outcome
d13b1a1ac56 Update marked to 2.0.0 (#117714)
403851e4be6 force async to resolve in exp service
94447bd20e9 Use button foreground on hover
3a6957333b1 call saveMemento in exp service
1e25d0c49bd Add details about what to do if createSession fails, fixes #117409
1cd0c337672 chore: add crash id for windows and mac arm64
9e83108e8ab Adjust bottom cell margin
cda3b7e157f Tweak cell toolbar position
6d63655a758 Adjust top cell toolbar position (fixes #117676)
3bfba9fa221 chore: bump distro
5b6dd28057d Fixes #115861
9ba671094c1 Revert "Fix webview focus issues that prevent cut/copy/paste when opening files with a quick pick (#116899)"
e5096a31692 Exclude z-author-verified from issues to verify in endgame notebook
14243220e50 Bump distro
75b26c1e5e4 debug: update js-debug
ae186be4703 cancel disconnect runner on attach
57c918802b8 Fix up types, make `done` always boolean Fix #117336
3516df762dd Fixes #116305: Add fake consumer of `IMarkerDecorationsService` to instantiate it
b91b917e9ae Revert "Add shadow to custom hovers"
dc04badf34a check if enablePersistentSessions before updating remote or local state
ebdf30f0887 leaks across notebook/contrib, fixes https://github.com/microsoft/vscode/issues/117687
dbd510ec91d Fix #113643
08073134158 fixes #116083
86fc2ba85f9 Fix #115425
54b88057c48 list: fix #116788
ca065c29280 Preview in Editor button showing in web Fixes microsoft/vscode-remote-release#4557
e6e61368ff5 fixes #114933
a5c6a900647 Fix #117612
2e63ec65ed4 fixes #116883
059e5798a24 notebook updates
44afa91ef6f also support when in viewsWelcome, https://github.com/microsoft/vscode/issues/9303
1b83aa0bceb Merge pull request #117472 from microsoft/alex/improve-connection-timeout-case
83ee8419e57 fix https://github.com/microsoft/vscode/issues/117640
abf2f3f6c83 node-debug@1.44.17
1f7ab5005ee upgrade to final version of DAP 1.45
9efc326b9bb fix https://github.com/microsoft/vscode/issues/117594
b85eb124d86 update milestone
6ade3e32968 Fix #117504
59c31364c70 Revert "Revert "chore: bump electron@11.3.0""
93c941bef89 Adjust markdown bottom cell toolbar (fixes #117626)
aabd93ed35f fix #117367 Co-authored by: Eric Amodio <eric.amodio@microsoft.com>
d37f3ffa392 Merge pull request #117645 from microsoft/merogge/hidden-term
105e8eec285 Revert "chore: bump electron@11.3.0"
51b93e40269 Fix #115320
805e7f281c3 fix #82587.
1582402b61e Fix occasional non-restored terminal buffer/title
1ba3ea20d68 Fix #117345
1a1178165db Actually use the tasExperimentService
6d0ce95af4c fix #116713
a708ba7a587 Update authentication provider doc strings, fixes #117409, fixes #117411, fixes #117414
d83895acf79 clear terminal layout info on window close (#117496)
8de95c02dbe Check to see if widget has been disposed of while actions are resolving
f4065074e71 fix #115209.
05d3593f91e fix #114936.
7f481d2fcc6 Make added, removed, changed, optional in auth session change event, fixes #117469
2852916b59d Pass scope directly when signing in to other account, fixes #117510
12f68ec7758 Fix unclear row focus in settings editor Fix #117527
73432445e56 Fix markdown cell going into edit mode when clicking a link Fix #109679
377ce5a59e1 Add feature flag for opeing to first incomplete section Closes #117533
c413a1c7aed fix build.
778e21ed452 Fix #117597
663159f2fa7 fix selection after multi cell cut
e62f7e8a458 Cancel disconnect timer on attach
3b06d2d1f33 fix #117458
f1d434309a8 Revert to link styling fixes #117539
caff7f4dcbd Fix #117336
07340c27f59 fix #117449.
22af2a11415 asFileUri -> asBrowserUri Fixes #117592
acfdb2d7ac2 Fix #115895
90cc8b14687 Only record layout info for shouldPersist terminals
213757cd5b1 fix #114031
faccfff275e Make terminal test less strict
8042e9b5d56 Pass should persist to pty service
80ea6efb4a1 Add shadow to custom hovers
fc61668a51e shared process - further delay spawning
20503c4da96 #114031 fix error
53fc5f7bb59 fixes #117256
eba4c1bc1ea debug: document context keys
c9042f49856 Adds force option to defaultLayout
d3b777f46c9 fixes #117348
48d47c8715c support when suggestions for keybindings and views as well, fyi @bpasero
0f6eda5348b fix splitview glitch
c1409aff832 fixes #117205
c783c26590e fixes #117391
8c98454f292 fixes #117478
fda43de2e5e untitle.hint: default should be hidden for this milestone
93bdc6cb71b fixes #117480
8d9b2e65bd9 more tests for https://github.com/microsoft/vscode/issues/117273
a63be52fdef Fix strange port label Fixes #117591
ff4bacb0ee7 Merge pull request #117535 from microsoft/term-disconnect-runner
134623067a2 Enable output based port detection on Mac and update default value of port source setting on non-linux Fixes microsoft/vscode-remote-release#4530
a799375663c fix https://github.com/microsoft/vscode/issues/117456
e7150f1fd3b add skipped test for https://github.com/microsoft/vscode/issues/117273
0d0cb2afdbd Inform pty host of detaches
90af0b9e3b7 Update enablePersistentSessions docs
3139dc7f927 Consider enablePersistentSessions when shutting down
1763c171a33 Merge remote-tracking branch 'origin/main' into term-disconnect-runner
4e467af0d9a Shutdown terminal immediately on last listener remove
b3b60ff1162 icon contribution: make consistent with icon themes (fixes #117492, for #114942)
57c6bad938b fix #117549
198dbb7a71e Simplify handling of pty host ID after restart
51a40b29e00 Fix #117566
3f987d64f0d fix compilation
f6f723e461f Save old cell paddingn in ports table
f6e68f4b4e5 #117391 get view by id
5e16cc37c6b Make input box fill whole Port cell Fixes #117386
c47da720f35 Fit input box height in Port table Fixes #117385
01cfa2f8352 shared process - spawn it when first connection kicks in (#117422)
3f868139394 Tweaked open issues query
aecbf77878c Improve titles of some port actions Fixes #117389
40ea1c99f8b Populate input with port number for Set Label Fixes #117390
bf65bc620be Use del to close port on Mac Fixes microsoft/vscode-remote-release#4534
5bc7c69ff66 perf - make it clear that shared process connection is after workbench ready (for now)
6e76d2520a9 web - remember last used workspace for extension debug
09a093d0d89 calm down integration tests
763e089ae54 :chore: consistent event names
7ffc518372b Notifications and feedback should not be visible at the same time (fix #101376)
6c179b9abea Pick up TS 4.2 final
a8c82939a7a Reducing padding for markdown cells
c13b21f7f8c editorType => viewType (fix #117451)
4e1234963a1 Fix #117340
4aa87166310 Update z-index for notebook left focus border (fixes #117528)
520188808c6 chore: pick up latest electron v11.3.0
075c5811b9d fix #117503
8e8c6a07dfe re #117451.
5713f288011 testing: don't go to source location when expanding/collapsing nodes
c5edf95dc6f testing: show hidden tests if reveal is requested for a hidden test
c2e66ea5697 testing: show retired test glyph margins as dimmed
f66e523dc3a testing: fix overflowing lines causing misalignment in peek
816040208dd testing: make auto run hover indicate current state
1550171b26f [getting Started] LogService: info => trace Closes #117443
91abaaa0cfc debug: bump js-debug
edd66c7c132 dedupe identical inline values; fixes #117419
80a1d7982ac Use grab cursor for rendered markdown cells
79b14947e7a Polish sign out dialog, fixes #117473
67261dc97fa fix typo in sorting; fixes #117375
fb3719c43e6 Focus editor when switching to notebook cell
45e71f054b6 Add completion for 'onAuthenticationRequest' activation event, fixes #117421
5c200bcc082 Improve handling of connection timeout limits
a5a8392079e Use registered auth providers instead of declared for getting label, fixes #117463
6fa58b5a863 Show provider label instead of id in sign in prompt, fixes #117461
1647961f7d9 Don't confirm on exit on reload
041e4d9b1f5 fix smoke tests with stable build (fix #117420)
763bfde29aa Remove proposed API check for registerAuthenticationProvider, fixes #117427
ece247a4f75 Don't clear accounts badge on cancel, fixes #117357
85cff833c28 testing: fix potential leak of projection instance
edc4abbc534 testing: fix MainThreadTesting disposable fishiness
d5a62bbe063 Fix Ports view context menu when no item focused Fixes #117393
2d6cc94a7cf Remove + action from Ports view title Fixes #117402
c1488d86c53 Better row aria label in Ports view Fixes #117404
cb3a048f5af leak of not used monaco editor in cell template
28a40e373cb fix #117300.
c2571352471 Removes extra command
e8351c2c2a5 Add better narration for + row in port table
c1fb9152a12 Better grouping on Ports context menu Fixes #117410
dda96b69bfc Remove debug logs
9c8882d8b7e Improve fix for #117246
9ecd3fc3022 Fix case with notification about un-forwarded port Fixes #117246
ded52df565e enforce segments in contributed icon names (for #114942)
9d1e8fa608a window - log crash reason too
4ee5bfc4b11 untitle hint: add telemetry from
13caeee4920 Document context keys
91f4ebc32d1 Remove code added to diagnose test only (#117244)
7222dfcffb5 exempt AuthenticationProvider from provider-naming rule
39b45dd9c0f Bumps version of github-browser
e4364e5f5da fix #117254
d2b24cd57b7 check if configuration is disposed
bd74308b5ab Revert "Merge pull request #117069 from microsoft/roblou/refactorKernel"
4673316a396 Fix #117284: Get started content becomes hidden on click
6312db1e01c Fix #115041: Path to untitled file from search editor is wrong
d54923b7f8e Add manual override for getting started treatment opt-in
b1831abf66d Fix folding of custom rendered markdown cells
b3a33306fb4 Add markdown emoji for testing in notebooks
b22f8f11698 Fix virtual file system resource loading inside webviews
69c0ce82f8b Add logging to better understrand getting started experiment rollout.
c159b34535c Merge pull request #117069 from microsoft/roblou/refactorKernel
ba3bd11ac7f fix kernel cache and add unit test for kernel reg.
1fd9f9eb286 Update test for api
eff172b7dd9 testing: better documentation in .d.ts
9cd0f2e8a4e testing: fixes if no document hierarchy is provided
e4a082af7f1 chore: bump electron@11.3.0
4ae248a0134 Remove leftover "runnable"
ce45b0d004e Infer cell "runnable" from notebook kernel state Fix #106747
65711c63dac Begin eliminating cell runnable metadata #106747
b9f20c79cbd Move kernel/execution code out of NotebookEditorWidget for testability
6a9f8ac7582 Rename markdown math extension to notebook-markdown-extensions
6a6b9a5cc89 Possible fix for #115918
a1f638e838b Changes welcome views lifecycle to Restored
08eac1a22dd Merge pull request #117204 from microsoft/rebornix/nb-selections
67ded110200 Add authentication provider registration to stable API, closes #88309
b6377b8e71d Handle promise cancelled for codeActionModel
2b44e04c101 Merge pull request #117292 from microsoft/tyriar/combined_id
a8451610bf1 Allow issue service to display a bug report window when remote extension host is crashed (#116896)
ffae9a4baf9 Encode pty host id into terminal id
3214b95098a 💄
4f25f18bd77 selection handles are only used in edits.
5428ab54c98 fold element should focus the cell.
413963c489f Remove editorOpenWith (#116856)
cdd7066f009 Allow Markdown-Rendering Without Providing an Env-Parameter (#117041)
5e067109a3c reduce use of handles when possible.
1cc57241cfe Update Codicons - Update debug angles - Update `new-file` icon object - Add `debug-rerun`
9703977dab6 update workspace trust status bar visibility
a776fe9af7f feat: allow excluding tests from runs
967497247a9 fix #117087
5b943120a12 fix focus/selection after cell deletion
3dde0402069 fix #115740
e33dda9e461 Update warning icon color to meet CC (refs #115799)
6d41b4e1ce7 embed primary into selections.
9a104a34ada Update `breakpointCurrentStackframeForeground` icon color (refs #115799)
e54948aa8f2 fix output on pastedcells
ed3eb3fdf23 Merge pull request #117100 from NotWearingPants/feature/debug-save-before-run-setting
e70d90fddf3 Hide badge if trust state changes
5654c838e8e Emmet: add support of multiple extensions path (#117105)
5bab307980f Bump vscode-emmet-helper
fca88ede1ee fix type of getValue in debugService
d8bf53de7f6 improve descriptions of debug.saveBeforeStart
427d9e1fc6c fixes #117225
9818531cca0 Merge branch 'main' into feature/debug-save-before-run-setting
e97e4135fc7 change options for debug.saveBeforeStart
9cc75d0e923 workaround for stoppedLocation.column being 0
b4518eb44e1 fixes #117223
ed08a141110 selections[0] is primary.
42e8d3eeb89 Fix select session behavior, fixes #117266
31aa03fcc8c Closes #116361 - adds select/compare ability
3c31b0debac Fix #116214
b597d6123fb move comment related to resizing terminal panes from code to issue
97fd4b9db42 Update go home contribution (#117097)
986996a7dab perf - add a mark for how long it takes to connect to shared process
072ec46dcfa new install proprosed api (#117059)
a0945131a10 Cancel mouse down operation when the editor height changes (#113818)
f1d92e78960 Remove Edge Legacy workarounds
086ccb15b3a Remove support for MSGesture
3c0970f6fc7 unwrap the actual command id when a command that required indirection fails, fixes https://github.com/microsoft/vscode/issues/116932
d08c3989a7d word navigation: on windows let the native chrome word navigation take over
17b26788b9a textAreaInput: respect the selectionDirection from native text area
e722803d927 dispose models that aren't needed anymore
2362b7c7d6c 🧹 remove unused disposable store
472c88618eb builds - same timeout for all tests across OS
1a6f64ef1de fix data loss issue #116600
05ea4c5e4e8 Removed optional message, and added modal parameter (#117241)
524e119a8b1 remove colon from git host in askpass arguments (#117230)
ea2c1e5991d fixes #117237
b273be79079 publish vscode-json-languageserver@1.3.4
3d455784e72 JSON Language Server 1.3.3
912792b418f JSON Language Server 1.3.2
e938901e2ab fix vscode-json-languageserver readme. Fixes #116720
e33c868876b oss tool
4fbb5f84857 work against layering check...
277c60fc0a2 💄 event usage
b64997e0c70 add nls message for icon property (for #116198)
cdf30a97f81 Update distro
b237599ad2f use browser crypto when it is available
d6846fa9e73 Merge pull request #116449 from microsoft/tyriar_megan_reconnect
218ffbf7d50 Right align actions in ports view
46acd748a37 don't trigger snippet completions on any whitespace trigger character, https://github.com/microsoft/vscode/issues/117194
1a45abdcf2d use `null` to unset metadata properties, fixes https://github.com/microsoft/vscode/issues/116956
ce7cd0abac5 Make env var tests more resilient to other terminal events
d2a6dea3236 Disable conpty in integration tests again
1bddccd4537 Use less aggressive create process timeout
d8b302db251 Merge remote-tracking branch 'origin/main' into tyriar_megan_reconnect
5e01284378a Ensure pty host is shutdown when shared process goes down
3c9cfeec32e Prevent env var reload when attaching
3781f94ba41 Fix build
ad275765b1d Update distro
35d3403f4c8 Remove log
b8f402dbbf3 Use + for port forward action in table
9a9d468cb68 Show table row to forward a port
61539324eb7 Merge remote-tracking branch 'origin/main' into tyriar_megan_reconnect
7e3476baba2 Add "Forward a Port" to Ports Context menu
4cbd8ce1e81 bump repo
a1e96b7c1e0 fix compile error
2b27630d361 editor memento - remove fallbackToOtherGroupState (#102485)
aa2abaa2f06 bump distro
63a4baf2e16 Update endgame notebooks
ae0a103755b :chore: address some todos
3860c90cd82 limit editor title bar action to 9, https://github.com/microsoft/vscode/issues/115198
e70ba206ff5 Update README.md
7d286c50c7a enable tsec tsserver plugin
f40b36524e0 update tsec
e427e5280cb fix tests.
2104d28a324 fewer changes.
c38aa5a341e file cleaning.
92c0878f39e shared process - drop the 3s delay for spawning
a830cb5f74e some code 💄
f294b6f8109 editors - replaceEditors should take care of dirty editors
00cb6865ab8 keyboard - document my contextkeys
cbcec2e1b46 support setting selections with either handle or index.
cfd62b3e2d4 reduce use of selection handles.
dea95d3e4f6 map handles to cellrange in UI.
8d9634abac3 Merge branch 'main' of https://github.com/Microsoft/vscode into main
7d143f79422 Fix typos
1e0adc0da5b unnecessary null -> undefined.
6e3e72705a8 Merge remote-tracking branch 'origin/main' into rebornix/nb-selections
de956ce8bdf differenciate selection and focus.
11cd76005bc Fix dep cycle
719256e1f14 Don't scroll when clicking on a markdown cell
f1551b6e7e5 Extract the generic message out from FromWebviewMessage
94f8212e2ce Add more specific contribution for notebook markdown renderers
4feadc39987 Fixes #112164
9a7da51af26 Make new markdown renderer better match old one's styling
75c39b01f11 Note that __vscode_notebook_message can only be true for webview messages from webview
d24ad98e314 Convert to switch/case
8b72fdc3e99 testing: unit test err
c3a45004a06 Pull from exp service to determine defaul startup editor value
e8966ecaa95 notebookeditor.selections
a0e24147e05 testing: remove duplicate extension and internal IDs
513c68ac8ec fix powershell 7 64bit not showing in 32bit vscode on 64bit Windows (#116986)
78707e2d796 Fix #117098
d615e8fcf24 add debug.saveBeforeRun setting
c74bc68f0f6 Hide markdown preview cells when they are folded
6e08e452465 Fix issue #116591 (#116885)
32a81335ac1 Remove unneeded event declaration
cc92705891d Flow control constants to platform
cf93ca4117c Remove duplicate interfaces from workbench
bfa04d48c83 testing: comp error
04957f6bdb4 Handle shutting down all window processes when not a reload
36dd567011e testing: make reveal in test explorer work
095b565283d testing: do not show test decorations in diff editors
1475cd0c07f Group common pty service interface methods
f3b46e33a2a Improve ptyService side log format
0f6ef54b4bc Fix replay position
5ba8f6e7ec0 Fix webview focus issues that prevent cut/copy/paste when opening files with a quick pick (#116899)
5d2c9bf2996 Consolidate `wrapWithAbbreviation` and `wrapIndividualLinesWithAbbreviation` in one command (#116603)
e66f74e0c2e testing: test feedback for decorations
89eb21418db Clarify layout obj is not referencing pid
fc28fad663a Correct reconnected active terminal restoration
a59c8d2e395 Pty service better title handling
d29d7e023b6 Add ! as stylesheet trigger character for Emmet, fixes #117020
8a4a7128977 Simply onExit handling
71ddff460bd More ptyService clean up
f9245a64b31 Tidy up persistent term events
392db917c0a fetch -> attach
f0ab2d88536 Return Promise<void> from fetch proc
d19fccbcf18 Clean up
68a4faad817 linkDetector: fix tests
55260619e78 Update src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
bd00c624a88 skip test to unblock build
2b230e4b267 Azure DevOps build task to download built-in extension details (#116938)
88c471ed62f Merge remote-tracking branch 'origin/main' into tyriar_megan_reconnect
6d451222829 Improve seconds logging
ee820dffbf1 Update smoke test README (#115582)
f6894202fea debug console: better hover text for tunneled uris
eeff347cac7 tabs - do not trigger relayout from updateBreadcrumbsControl (#112630)
61df1625efc assert no RPC leakage in notebook tests
3723081d639 separate vscode.NotebookEditor from ExtHostNotebookEditor
dc120dedc16 tabs title - 💄 height compute
f85b50f7491 Change filter on filter view when view visiblity changes Fixes #116815
a3fc4ce5406 remove console.log
d050858b5dc fix tests
2ca2792a65f fix smoketest
443be92d9f1 improve link hover in debug console
5e63a2f4ecf cleanup, NotebookEditorInput#viewType is actually never undefined
102f5ea0fd5 Add period to list item for consistency
febd96f0e35 debug breakpoints: remove breakpoint inline action
a30262f0b00 Fix #115763
9fe7b6446dc support setTextDocumentLanguage-api for notebook cells, fyi @rebornix
07a458dd681 open editors: new unititled file in title area
e09a46e017d use document directly, not editor.document, for $acceptDocumentPropertiesChanged, fyi @rebornix
4a74fa81c1e 💄
57cd5d4936c 🪓 remove unused $acceptDisplayOrder-RPC and everything around it
d240f119d44 strictness (fail fast) in extHostNotebook
93ec7113e12 don't bind notebook document to a provider/extension, do then when calling backup, fixes https://github.com/microsoft/vscode/issues/117035
7e7a71d7332 💄 more supportsBackup removal
84a3473d324 views: fix buttons width
bfcaefe74de untitled hint: change default to be button for the user study
ba7006088b0 tests - more logging for #117032
bbd39767eea sandbox - document issue with #116829 in code
a47f3244b36 add doc for what workspaces are supported
a98f29fd9c9 fix compile errors
c4ac419ef91 remove unused cast
02b2629dd1c cleanup, all notebooks must support backup
fa6c46b74b2 Merge pull request #116968 from DonJayamanne/fixOutputMetadata
03d71ec1f70 update distro
1f7f9dd5e6a use keys for sync from product
a6fa62809e6 tabs wrap - allow for up to 1px overlap of last tab to action toolbar before disabling wrapping tabs (fix #116385)
f9ed8037156 Move Ports view into the panel
a8a04eb7d16 joao/table (#117026)
c523e48e518 extensionsList: focus only enabled items in actionBar
b9eb461aa24 tabs - allow badges when tab sizing is set to shrink (fix #115908)
2efcd2bcd2b Merge branch 'main' into joao/table
5d4d796b9cd remove doc
c96f842dc58 Add icon column
7a40161c91c revert default value for workbench.tree.expandMode
adccb9151f4 fixes #117006
97dfc57ffd6 tests - a lot more detailed getUntitledWorkspaceSync test (#116288)
c9cbeda067f actionBar: allow to go over disabled items
6186bfc78f6 files - make save error actions context aware (#115840)
d8b1c8d697b Merge pull request #116964 from microsoft/sandy081/fix116722
f1de1700dd5 editable changes in notebooks
d151e0a33c1 Fix #116199 (#116268)
d53a27d7c20 Fixes rendering issue in Firefox
73ccfc027c9 Oops
192c817fd35 Make jsdoc completions text kind instead of snippet kind
9f08368e926 Handle normalized absolute file paths on markdown preview link click  (#116649)
094777f3929 Fix alt for menus inside of webviews (#116830)
096e5555b6d Allow welcome page to not be active on account of focus potentially going to a getting started item.
ba05eeda2e3 log something in ptyService
c3695af6d27 testing: fix unit test
a172be74ef3 use persistentTerminalId instead of pid
5a0bf3751ab testing: add method to publish extension-provided results
52ebf0c7f87 Add 'deny' option to account access prompt
ca02f19daf3 Fix #115314
482013c77e2 set minHeight on outputs when rerendering outputs to avoid shrinking.
8f2e85abd60 Fix #116574: Make it easier to jump from one Getting Started section to the next
1d3343a1091 remove stuff from process in platform
8806d063fe6 Enable extensible markdown notebook rendering in VS Code workspace
25c0fb7f2f6 Fix _getViewIndexUpperBound throwing if the view model is undefined
03b6a2e6b73 Null out webview on dispose
d1313311956 Remove extra info from onDidChangeSessions event
dd2bb8cd3ac Update src/vs/platform/terminal/electron-browser/localPtyService.ts
45dc2f5fa0f testing: allow contributing menu items to test view
88f459a2adc return terminal launch error
7aff64c42d9 Remove unused
840f19af066 Contriburte extension items at top-level Ref #116414
9c8e2ae7afb move stuff back to workbench and remove log statements and use pid
e95a5c1e1c0 Update src/vs/platform/terminal/common/terminalDataBuffering.ts
2d263be14f0 fix #115722.
b882940dc6d align InlineValuesProvider with EvaluatableExpressionProvider
a90d4ab5cf4 Move notebook markdown cell margin to its own const, tweak margins
070a33c7d62 Update src/vs/platform/terminal/common/terminal.ts
8039b6416c7 Update src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts
6fae7792bb7 untitled hint: polish
98c1cd2ca88 untiltedHint: introdcue button option, use it as an editor contribution
0eaf2bab81c enable flow control for local terminals
9c77f4d86aa add NotebookDocument.save().
df04e1388dc fix #115596.
f79a2119bd9 fix #115326.
933ca3a395c fix #113381.
e8836805dca remove attachedEditors.
bcc49ca4b67 testing: fix comp error
f4ce983bcd7 Open first section if no items completed Closes #116570
657398dedfa Back => More Ref #116570
7130344e98f Merge branch 'main' into tyriar_megan_reconnect
26b6f4d0889 testing: fix show in active file not working when first turned on
ba168d0cd71 testing: show discovery progress when finding tests
e3dc574a51e move terminalDataBuffering from workbench to common
1250b64cfa1 💄
d9dd7f0b0e1 revert focus tracking changes and use it to set focusable on actionBar
6cc6794dbb6 Support remote images
33dc53fe956 Oops
70c4b5defa8 fix initial terminal title Co-authored by: Daniel Imms <daimms@microsoft.com>
6b7bb2308b2 Cell output metadata to be added to Notebook Model
13a9be855a1 removed unneeded events and fix reconnect title
3fbab260e39 only start process once Co-authored by: Daniel Imms <daimms@microsoft.com>
e9b451094e8 fix #116722
69d39a0ed3c send event when removing a kernel, https://github.com/microsoft/vscode/issues/115698
7bca8a91b4c send correct delta after restarting extension host, https://github.com/microsoft/vscode/issues/115698
63a9d5aa562 fix tests
50fe3228e48 Add tooltip to icon in ports view
2bb9fdfa8c2 Emmet: add css.color.short setting (#116912)
7effc11c792 Bump Emmet version
ba97aa53374 Add padding-right to port cell icon
2a12fd7202d dispose more things, https://github.com/microsoft/vscode/issues/115698
a246f643eea debt, copy-paste police
ac38da16b67 Merge pull request #116954 from microsoft/tyriar/heartbeat
7d57388aebe Tweak title source, create proc timeout
b827a113d40 Mark disconnected terminals and disable stdin
fba2cda1fa7 Handle non-responsive pty host process
7b74c7787c6 Fix hygiene issue in breakpoints view
26dff8f2cca table hover feedback
777c51f046f table: optional tooltip
29d4fdb65c8 Fix #116829
ecd60db2505 reload non-dirty notebooks when their files change on disk, https://github.com/microsoft/vscode/issues/114263
31e3a7794d4 merge NotebookController#reloadNotebook into notebook editor model, remove NotebookServce#resolve and add create and fetchData "primitives", https://github.com/microsoft/vscode/issues/114263
7d74c5d4b05 💄
2a1f11a296b add IResolvedNotebookEditorModel and use that in most places so that we can remove non-null assertions
692f1465a82 Fix #116691
ed801381331 More clean up and fix icons
e8928ea6789 use product name
c714b56e804 Simplify events in LocalPty
590f7bc0896 Use column weight in ports table
7e674bd5a7f Add port header tooltips
c0f7c4cf9ab Add tooltips to port cells and some cleanup
a65139f4bbb table: column size constraints
200323caf6d table: column header tooltip
e1e5f3810c5 table: fix weights
e10085761b1 Update distro
fdaebc1f110 Merge pull request #116373 from microsoft/tyriar/megan
da0086512c2 Update distro
666351b321d Merge remote-tracking branch 'origin/main' into tyriar/megan
a6cc65462a2 Re-enable pty host restarting
16510dfc86c Remove logs from test
9e61f455450 Source -> Origin and added a menu
9e6e47cea1e Show detected ports and add input box
d5d0bf7b073 Some clean up in naming
9b9688448ab Hide privacy column
49378fc9a58 Use container in renderTemplate
edab4b7bdc9 privacy and source columns
6d7eefbae2d remove unused imports
7efe1382bbe update comment
df97ef2288a tunnel view: enable context menu clicking
5d8db7c493f reenable tunnel view list options
9752a1cb3e0 reenable more tunnel view functionality
d15bdd6aeec cleanup workbench lists
3203a54e0bc More actions on cells
eb50a52badc update distro
0f120bfa7cb move IActionViewItemProvider and IActionViewItem into its right place, https://github.com/microsoft/vscode/issues/116112#event-4345173898
30ae7b194e6 Merge branch 'sandy081/settingsSync/align' into main
869fb74662b Merge pull request #116901 from DonJayamanne/fixRunState
eb21069624c treeItem.iconPath no longer works with files in globalStorage in Insiders (fix #116735)
3b6599f6ba9 debt - remove IActionViewItem from composite (#116112)
63cbe73b2f5 chore - consistent imports
ba8d76eb971 Improve notebook toolbar overlap of markdown cells (fixes #114730)
42289086600 Fix loading spin icon (fixes #116898)
6eaef7d42f9 Add postNotebookMessage helper function (#116909)
4af885c6121 Take `string` kind in `_executeCodeActionProvider`
b0360851d4e Mark events fields readonly
a2a3bf27e9e Fix hover for notebook cell
cb95415caaa Revert back to old node-pty
473c7ddd500 Ensure tests run to completion
714b41738e4 Adds id & version to extension context - #116906
58f86d083d1 Fixes to enure tests complete
7160c4e7b50 Fix suggest widget explainer commit character field having extra commas
be6225f669b Fix markdown cell focus indicators for notebooks (#116813)
b09a71dce78 testing: update test results api to spec
00ca99f5672 testing: fix not being able to type spaces in filter
45ad634581b testing: show placeholder text if providers don't discover any tests
c0b69b03a9b Ensure runState is updated correctly
c484ebb065c chore: enable compression for crash reports
429fa749e78 reconnect processes Co-authored by: Daniel Imms <daimms@microsoft.com>
6dad35394fa Update copyright year
6e908f57c7c add debug logging for configuration
608e8791ff1 Add back support for reading from clipboard in webviews (#116597)
086112d4967 move cell output tests to document.
0354f334edf remove unreached code.
8cec47ff4a3 Update Codicons
4f12bb8451f First cut of allowing extensions to contribute getting started content. Closes #116414.
a5ff0dd6eee Return from getSession earlier when requesting session access
4e19a9f16ab Update telemetry classification type for isEdu check
31e27a8d3c9 add trigger replay
5a4f5c95fe3 untitiled hint
00b583d38d6 💄 class name fix
4a2bb3569e7 Localize terminal context key descriptions
84a3428e924 update distro
f1aee41e1fd Merge branch 'main' into sandy081/settingsSync/align
108616d3590 support switching settings sync services in web synchronise setting sync service type in web show necessary prompts when services are changed
bd5d97dbce8 Rendering for local address and label
c65da0b1d62 perf - init KeyboardLayoutMainService in parallel to window opening
ab848457376 make 'editor/title/run'-menu generally available
83d540c4bfa 💄
a94e67e5e1c InlineValues provide: merge and sort segments per line
a16b41d9c49 adopt WorkbenchTable in tunnel view
43262ab61af Add editor input factory
03ad0f1f8d9 workbench table
8244f999659 table: rename
8e003e63804 Adopt description in terminal RawContextKeys
6ecae6f5f94 shared process - log errors properly
79f90304beb refine completion provider for context keys, https://github.com/microsoft/vscode/issues/9303
29f80fb60f6 🆙 distro
154c94ef3b1 Update terminalView.ts
9de38fc9a80 Disable keytar in our integration tests (#116852)
d7230651acc Remove old workspace trust editor
797dc143ffb Fixed command, added spacing
5daa0b3b59f Fix right click paste
5816c4ea2c9 Improve tunnel label and process description
0cf9477e966 tunnel view: start to adopt table
5870204e95c make notebook and cell metadata classes, https://github.com/microsoft/vscode/issues/116333
0ac9125128e table: styles, domFocus
8615af08b3d Tweak input field width
f2a1ecc9a7e Add workspace trust banner + UI polish
c1230f88475 shared process - log errors/crashes also to active window
4006dd2e4fb table: use getSashOrthogonalSize
e8b48607298 splitview: getSashOrthogonalSize
589a0f268a3 further TunnelViewModel simplification
037b4b161a1 simplify ITunnelViewModel
678acbe5364 outputs in notebooks
13070015bdd expose context key info command, add first version of completion item provider for package.json and keybindings.json files, https://github.com/microsoft/vscode/issues/9303
44dbd182557 Wait for tree to be registered before disposing This fixes the tree view rpc test Fixes #116776
1bf78c50fe9 add NotebookCellOutput#metadata, also use API type internally and translate dto sooner, fixes https://github.com/microsoft/vscode/issues/116792
7a0caf4d86e Let Remote extensions set port source (#116838)
d3f2e22c19b table: css
fe02cd157d8 table: fix initial cell sizing
89b85a05d43 storage - more consolidation
bb999b90b45 table widget: fix overflow behavior
f290c162de7 table: layout
3f0d8a14759 storage - some 💄
45704f8f340 storage - lift more things up to abstract impl
a36e9b3e092 add prefix to main errors when logged into renderer
90f5ef65a09 Delete notebookTestMain
c03c7587651 Select the first search row when initially focusing it from the search inputs, now that the coloring is easier to differentiate
79b8259abb8 change cell language with cell change events.
b89dedc5d03 Add onProcessReplay to LocalPtyService and forward the event to PtyService
5d08a5663ed add onProcessReplay to PtyService
dcf7f714e1b add onProcessReplay to PersistentTerminalProcess
b3f8737839d fix #116808.
b0bd28137a6 add test for #115855.
90c5ceafc38 monaco: fix conflicted file
dfee0857c23 testing: run test on enter press
269cf7a98c1 testing: improve labeling in peek for accessibility
69393e9a2fa testing: improve labeling in peek for accessibility
3d19580d17a fix: hide debug/run actions if no tests are applicable
b050d09527b testing: filter focus on view visible
da1439d5dba testing: tweak autorun icon checked state
12677674727 fix #116598. broadcast output items change.
74594435504 Update monaco.d.ts
0f05597b851 don't re-create a persistent terminal process
2cc13674e33 Also bump build version and run formatter on all files
52d1b626f31 Pick up latest TS version for building VS Code
f3e3ea98946 rename remote -> persistent
6f23480f3b1 Remove bundling changes
e7d2a864e4a testing: add contextual commands for running tests
c41fb762991 Re-enable all tests
14923b5427a Allow conoutSocketWorker in unpacked asar
939038aae9a Recursively include lib
197f453aa95 Show tailored notification when paste isn't supported
e091e894b57 Include lib in node-pty
f08f99a1546 Merge pull request #115855 from susiwen8/onDidSaveNotebookDocument
53d2a737761 Clean up focused cell styling (fixes #116797)
742051039d7 remoteAttach -> attachExisting, remove logs, fill in args
5c005324bb4 tests - enable workspace tests again for now
d22941af5d7 startDebugActionViewItem: fix focus navigation within ActionBar
22df9214fec Merge pull request #116728 from ugultopu/fix-misspelling-of-likelihood
68b67a34559 Keep misspelled property name in timerService
7ce6ee75590 testing: fix event listener leak
994ad375882 Log more in test
c441c567a31 storage - implement first cut migration support
35abaaf6063 Log all lines in failing test
3859ba936d8 Merge remote-tracking branch 'origin/main' into tyriar/megan
7a9867c841e first draft editor (#116599)
a17ad41546c use nls#localize for context key descriptions
3d0245d5e4f more table progress
6200437f3f1 add description to some RawContextKey-instances
8aa800e459a allow to exclude a context key from registry, allow to provide type eplicitly, https://github.com/microsoft/vscode/issues/114867
e537fd9e318 first cut of proposed "inline values provider" API
3385cc7a5cc 💄
c9607e61e0f actionBar: always respect orientation, so only left / right navgiate in horizontal and up/down in vertical
ee9da16746d table: intro
8d900267955 set output and editable properties
6b35ff74c14 storage - bring back tests for close on shutdown
2313132d554 💄
5fc7d91fb31 workaround #116691
974b2143344 rename: resolveNotebook is openNotebook
04b7b5ee4c7 storage - let renderer close workspace DB
2ad3fe12241 storage - skip failing test
d2cfc0792e0 update editable state
a1b9523db10 update my-work notebook
28de0a46867 Fix YAML typo
38ae92f4b19 remove unused ui tests
77493b59a55 storage - test all storages closed when shutdown
58a427566b6 Revert change
c967932ba34 Specify sourceScanPath
982b28f42db Merge remote-tracking branch 'origin/main' into tyriar/megan
58e22bc5226 window - type win as null if disposed
3dab064342e Move component governance to compile stage
5e74ad54302 storage - fix unused storage variable in tests
266e4759316 before removing cell documents capture its API objects, after inserting cell documents capture its API objects, fixes https://github.com/microsoft/vscode/issues/116711
1bb2e0a9bab storage - use inMemory storage for tests
a7470e5094b storage - let service own lifecycle in main and implement storage warming when window loads
f829a7dfd7e workaround for https://github.com/microsoft/vscode/issues/116751
ac916cbb2df don't assert rpc strictness yet
5662aecf241 actionBar: adopt respectOrienationForPreviousAndNextKey option in lists and notebook
55393229982 &quote; is ", re #115391
72137a82233 fixes #116663
f606206cc8f debt - consistently refer to main services
8dbc14946b3 debt - consistent event names in main
3bb3da8281d storage - move more things into abstract storage service
2b1ab52273b storage - remove unused onWillSaveState event (main)
bf0e8299db7 Fix misspelling of "likelihood"
3479bb35904 button checkbox and menu: do not automatically remove tabIndex from disabled items
5f5ceba51a3 actionBar: allow to focus disabled items
8263f1c66a3 actionBar: do not eat up the arrow key if there is only one item in the action bar
6c12d9f2c4a storage - add first cut lifecycle controlled from main side
e4e0919c0ec refine precondition so that markdown cells always "execute"
d9c653c8b68 increase default timeout for event waiting, fixes https://github.com/microsoft/vscode/issues/116704
2e53ffced96 add precondition to exec'ish cell commands
5901b6a4ea1 storage - move lifecycle into service
5f48de03e6c use metadata classes for cell and notebook document implementation, https://github.com/microsoft/vscode/issues/116333
f2a491fbc83 customSelectBox: do not buble key down and key up events to not conflict with action bar
762dc9eeea6 action bar: In case an action got disabled and it was last focused in the action bar We need to reset the tabIndex to be set on the first enabled item
8fe9b7c5ec9 Fix that keybindings editor input actions can not be triggered via keyboard
2ecfd145662 Setting for proc vs output port forwarding Fixes microsoft/vscode-remote-release#4274
3e2aebd790c Revert "use metadata classes inside NotebookCell and NotebookDocument"
18c04a57160 make `vscode.NotebookCellRange` a class
ebc30d6c92c fixes #116700
7bf4a3d823d fixes #115212
2a9b2181ffe improve list settings docs
96640b6b875 tree: remove bogus expandOnlyOnDoubleClick
d56305b3f9a cleanup imports
58b13a2fd1d Fix too many/wrong port notification Fixes microsoft/vscode-remote-release#4472
8848ddd9c06 use metadata classes inside NotebookCell and NotebookDocument
62d027a713c more API todos
7dc11581e45 remove unused event
4a941b1853a Merge branch 'joao/update-list-styles' into main
59afea597bd explorer:  click in empty area -> create a new file
e2d1cfb64a1 make SubmenuItemAction dynamic again
250c2265459 fix suggest widget styles
4077a67914b adopt focus border across all core themes
c4c044e20db fix quick input inactive focus background color
9dca2bed0bb Fix bug in tree view tests Fixes #113896
793371f0559 remove twistie hover feedback
f3b4f3f6acf unescape characters that marked escaped, fixes https://github.com/microsoft/vscode/issues/115391
e408bcafd1e Merge remote-tracking branch 'origin/main' into main
198bfdbfaa7 Merge branch 'joao/fix-116523' into main
7d338140c3b Merge branch 'main' into joao/update-list-styles
5c330b06d4d cells are editable
c9886c39462 missing recursion break
965518f9a98 fixes #116558
4d89ae10ff8 fix #116523
114bac541eb storage - bring back logging support
2af090f8a3b Merge branch 'ben/storage2'
ac5b7117ec4 assert no rpc in notebook doc test
059edf4166f Merge pull request #116685 from microsoft/job/nbtests
50bb1cf1a4d storage - do not init at random (fix tests on windows)
88089d3f204 fix terrapin failures not reporting
cc4d7e8a11a update (restore) language test for new cells
196bf678a15 reset dirty state when reverting a notebook, update extension host when dirty state of a notebook (working copy) changes
5236d344604 run active editor test only when having focus
02613ef2b41 storage - implement workspace storage and fix tests
5eca02fd99e storage - some 💄
23a780dbe73 storage - introduce shared class for storage in main
980becda8d5 main rename
a508b135382 storage - wire in close()
76fecd98554 storage - add test for storage main service
f49d78c4afc storage - fix layers to be able to use native storage service in sandbox
1f8bb6d33b3 storage - change main storage service to support global and workspace storage (stubs)
a699ffaee62 Reenable notebook smoke test Fix #116535
3a442c6939b Fix broken markdown cells The editor wants to create a scoped CKS which you can't do with an Overlay
05922f8a260 storage - add tests for all services
992cf6bd44d Update node-fetch (#116560)
0de32ce880b consolidate some code
647a4b044a2 Make sure we focus inner iframe contents if the webview itself is already focused
90f344fe7ef Skip echo test again
bfd81161b84 splits persisting, still some issues
a0e0324a8da testing: commands to run tests at current cursor and in file
07e3bcf7eac testing: allow filtering to only executed or failed tests
0e16b7a0fe9 Simplify echo works in the default shell
be7cf6f2e9e use checkmark instead of toggle lang 4 diff editor
2f277cb41ef Add github session telemetry event
8853436d0f9 Remove ps tree logging
1a4c9ac9f2a fix classic menubar safari
3d9a48e0f5f Revert "Bring ptyService into shared proc"
656c907867a Revert "Register ptyservice in localptyservice"
e9ecaca14fe Rescan task scroll container after task selection animation complete Fixes #116521
1b897365d72 Revert "Move ptyService out of shared proc temporarily"
6841c52357d Try conpty in integration tests
0e3ec619b69 Revert "Re-enable most tests"
0ebe81ecc1e Revert "Skip all but 2"
778ce3d6af2 Add potential top level command entries
7934b9d439c Skip all but 2
6693b29b19c testing: show peek link in hover
5c449afc04d testing: automatically open peek view on failures
53c2e1b23c7 testing: close peek view when associate test state changes
a5994556a8e Re-enable most tests
68f1497536a Skip echo works in the default shell test
8c1dbbbc588 clean some things up
1170b3158e3 Emmet: add output.reverseAttributes option (#116088)
af4a8f7ba7f use TerminalInstanceService to access localPtyService
66d300b1bb7 Enable 3 tests
7661c8e35cf Move emmet to emmetio/emmet npm dependency, fixes #110697
653f025dfdb Enable ts check for service-worker
fab9533c5ce Add some aria roles ref #115896
6148fedea06 Enable terminal tests that deal with ptys only
44477fbb74c Re-enable tests, disable terminal suite
27e1db98c12 Move some additional focus fixed from electron webviews to iframe webviews
2cb4179ec6a Make sure the webview gets focused even if the actual webview content does not yet exist
2e1166cb0c2 Make sure webview editor has not been disposed before claiming webview
0568d26fad6 Revert "Support the new 4.0 definition of isArray (#102413)" (#116571)
33d715555c1 Remeove "Skip" link, ref #114964.
1f45db9994f Disable api tests
f1202da4a00 Simplify search view tree height calculation Fix #116182
8912ec1803a Move ptyService out of shared proc temporarily
2d6c2d0b2d7 wip - move notebook integration test into our normal API test extension
5f9f03e8226 disable extensions when debugging API tests
1f1db8515ee while resolving an editor input it might get disposed
52f633d19ce some 💄, some API todos
888752f9241 remove node-pty from web
c83064b9825 Update freshExecArgv comment, fix #116422
14669c2e457 Make scopes parameter optional to getSessions and remove getAllSessions
a16f5d2c4c1 fixes #116395
ac1ba331274 testing: add tests for and fix bugs in test result service
4713b130e11 Register ptyservice in localptyservice
dc4fa4878fb Bring ptyService into shared proc
815694184dd Unrecognized variables with arguments getting truncated (#114474)
41339cc2a08 Make user data path a AMD/CommonJS compatible thing (#116530)
6a698d7d435 tabs - no need to lookup editor index
4e1b20a7d5b Log process tree after test suites
13d51e7c21e actionBar: use up/down as well to move focus
84534d243c1 Merge branch 'master' into sandy081/settingsSync/align
a56ce22cedd Disable ptyHost restart
138cfd777be Don't double dispose LocalPtyService
93da15934d5 Improve storage key for stored tunnels
d88249fdfda add notebookKernelCount context key, clean up non-null assertions in notebook editor, modernize contributions store
da6a819b54a Tab lists should only occupy a single tab stop
3eefea3b000 sync enablement keys and service key
a6be559d52d 💄 fyi @rebornix
cc0ccaf1c03 more disposing when dispose main thread notebooks, https://github.com/microsoft/vscode/issues/115698
e4d8575cafb Merge remote-tracking branch 'origin/master' into tyriar/megan
cb010970c7d Merge branch 'master' into joao/update-list-styles
781bcaeb500 Call shutdownAll on ptyService
5a7711ac928 💄
f507f5ca343 Setup tunnels for syncing
570890ca7e6 💄
fc31a6a5584 skip failing test, https://github.com/microsoft/vscode/issues/116535
2384f4de731 Accessibility: Shift+Tab gets trapped in debug and problems panes.
e7f29d65c37 use registerSharedProcessRemoteService to register
59008059d23 add devcontainer associations to configuration-editing
6d9611747ea wip: update list ux
868fb4c39f3 rename CellKind to NotebookCellKind
215cd172763 Merge pull request #116443 from microsoft/joh/kernelLanguages
82d255a3e34 Merge branch 'joao/overlay-cks'
968ce642c3c add tsec to CI, https://github.com/microsoft/vscode/issues/116459
bc72e7ab7e3 Merge branch 'master' into joao/overlay-cks
f83e5e49fb2 Merge pull request #116460 from engelsdamien/master
b06c9c66f56 🆙 distro
ed10bfb7c4f update tsec to 0.1.3
2911d1d1dd6 setting editable metadata
f0d62c6ec2d 💄 more main.ts cleanup
795db5b7194 Always intercept file protocol (#116522)
de9c04cae4a remove storage service, try to hook up layout info communication, bad layering also
6ac9a3ecb36 Add disable checkbox to getting started. Closes #114964.
767dd7033df Try different workaround for rewriting localhost resources for remote webviews
96718c6fe8c Add back build-notebook script
9b4f1aff5d2 Enable inline html tags in notebook markdown
ba8a5d8fff8 [Deep clssifier] Lock dependencies
263d4b75e21 Fix getSessions for microsoft auth provider
eceff533515 Rename login/logout to createSession/removeSession
ea865096f13 allow for tiered trust (walk the tree)
98354ad7cc5 Add comment about localization string
ff20de6a4e6 move more stuff into/out of platform/terminal.ts
1e46aab8d98 Update src/vs/platform/terminal/common/terminal.ts
2dea6ff4bbc fixes #116142
e4cf7f46ee2 Remove account caching from MainThreadAuthenticationProvider
650906c3697 Pass scopes through to authentication providers
a7758e4328b Update indicator height for collapsed cells
fb354b70b3e change import for terminalContributionsDescriptor
0c11d7c4007 undo move of lines in test files
c87e0171f70 remove unneeded stuff
d3502eaa4cb revert terminalTab change
7e6e069807d remove unused imports
3ba5101f27f Make notebook scrollbar transparent
33f7e89f610 Merge pull request #116409 from microsoft/misolori/notebook-cell-focus
d10f2e60328 Fix #116412: Use getting started page as default startupEditor.
8dd7a21bd66 Merge branch 'tyriar/megan' into tyriar_megan_reconnect
68a47518f87 move things back to platform and delete duplicate code
78de6c64b03 remove get*Actions on container
b49c2cba98a Dispose localPtyService on shared proc
5da54d318ad Dispose client on exit
3bd49afed2a Update src/vs/platform/terminal/common/terminal.ts
53ac8d3068b Update src/vs/base/common/async.ts
e21134dd71e testing: implement base autorun
e6bc652737c Merge remote-tracking branch 'origin/master' into tyriar/megan
2869ec9458c Clean up terminals when ptyHost goes down
a35338b2501 move things back to the workbench and leave only necessary items in platform
cf879190e74 sync resource enablement keys & service key in web
9118a3461c5 Make onDidChangeSessions event for auth providers fire complete session
42edcdb41b2 Use DAP's new "StackFrame.canRestart" property to enable the "Restart Frame" command
a9515960052 compositeBarActions: hasPopup: true for consistency
1887d9aa251 Accessibility: Accounts and Manage items role
7aa84660c1c Merge remote-tracking branch 'origin/master' into tyriar/megan
5908eabc80a app.ts - clearly distinguish node.js and electron servers
a4a87ef29f7 💄 more app.ts cleanup
25263592076 💄 app.ts cleanup
00a91fc8495 Adopt registerSharedProcessRemoteService
a9536c368c3 Merge remote-tracking branch 'origin/master' into tyriar/megan
cd95d465dc7 Don't remove node-pty/lib
493fa4bd31d 💄 main.ts
27bdcacfabc update distro
91c8be9a55f Merge branch 'master' into sandy081/settingsSync/align
1be536d154a Show DAP's new "ExceptionBreakpointsFilter.description" property in a hover
91b533066e6 post merge clean-up
e498c28de11 Merge branch 'master' into joh/kernelLanguages
90d07beb8a7 Show DAP's new "ExceptionBreakpointsFilter.conditionDescription" as placeholder in condition text box
0d7c8ec95a6 Merge pull request #115817 from microsoft/notebook/outputs
c514299b83e Show full url of ports when in panel Fixes #111378
ea048b87717 move ipc services back to e-sandbox
b2e68d70b8d registerMainProcessRemoteService & registerSharedProcessRemoteService
b31d9d5d06a fixes #116334
8d7dbbab619 Account for workspace files in auto task notification Fixes #115990
2033439e485 add description property to RawContextKey, all registry to collect all info, add command to print, https://github.com/microsoft/vscode-docs/issues/3039
58eb43beaa5 List all tsec exemption explicitly
33a92ebf4ac Updates tsec to 0.1.3
5a156a7fee4 #116084 fix reporting unhandled errors
481b65972b6 isolate IMainProcessService and ISharedProcessService into common
d10ea1358ad add more wordings to settings sync dialog
141a4712033 more IPC cleanup
662b0003b81 cleanup update ipc code
c544f38c93b Update distro
94c1ceb34f7 Merge remote-tracking branch 'origin/master' into tyriar/megan
ff26dba8c41 Set up proper logging in pty host
73e5f518cdb Merge branch 'tyriar/megan' into tyriar_megan_reconnect
2b5a5223cbb Fix case where file picker doesn't have .. Fixes #116457
6c92a6605cb Merge branch 'master' into notebook/outputs
62dd18f1efd Resolve todos
5de7be246ec TerminalProcessMainProxy -> LocalPty
1b72bb62498 Handle ptyHost exit gracefully and restart
ccc28e3726a Remove languages property from NotebookData and NotebookDocument
59264e2ab16 Merge remote-tracking branch 'origin/master' into tyriar/megan
5fc19f5f59b ILocalPtyService -> IPtyService
6ee4ef1c2db paneView: make actions in view title visible when focus in pane
474e769014c stop using `resolvedLanguages`, only use kernel languages or all languages
a0bbfacd8cf Fixes #116060: Clone minimap options before changing them
9737b1aad10 move INotebookKernelInfoDto2 to protocol, separate kernel from dto, renames
b6623e4d351 file watcher: show start watching info as debug
f644b6b2a96 debt - less any, more unknown
471be7f8e60 use web overrides while reading
55d267293b9 have a clear separation between KernelProvider and Kernel
6f1cfdbae8a 💄 jsdoc
7d5d5f5e7f8 wire up `supportedLanguages` from extension kernel
24d1235d904 some unit tests for metadata classes, https://github.com/microsoft/vscode/issues/116333
4557e4e4c39 Merge branch 'master' into joao/overlay-cks
6b8251cf437 fix #116419
16df123b5ae do not turn off settings sync when quality changed
3da19cfbafc Revert change to startupEditor until smoke tests are fixed
8398e68f8f4 Fix #116093: New search editor should be pre-filled with selected text when pressing Ctrl + Shift + F
775830334d7 Fix #115883: Remove opener service logging.
c6757e30a15 Enable getting started page as default startupEditor. Closes #116414
e3acfe5d71a Merge pull request #116212 from microsoft/misolori/extension-icons
cd7a2d66853 Aria-label the image alt text ref #115896
93f705ab40b Remove old import.
6896ec35ff9 Make cell focus indicator more noticeable in large cells
5720ed629c6 Add back icon to getting started tab
89162d522b5 Remove unused template file
1830cbfd508 Remove getting started opt-in's
e6d8271e2e3 Batch of getting started accessibility changes ref #115896
17018593c7c add to do
ebebd48ad92 adjust resizePanes
233890f2eb0 add log service
cd9704db38e Merge branch 'tyriar_megan_reconnect' into tyriar/megan
6dd156d04b2 Support drag and drop copy for markdown cells
1819dd5285a Merge pull request #116389 from microsoft/tyriar_megan_sharedproc
b262ce0ac40 Always put focus in search box when using command to open settings editor Fix #116167
35f855796b9 Add support for markdown notebook renderers  (#115191)
5188792bd04 Move ptyHostMain into the node folder
4ea18e96151 Remove unneeded file, document channels
6bdc6bb24b3 Clean up
25c680caf4e Create ptyHost, bidi communication
c36a09929c8 testing: implement retired test state
da39b7af3ea create PersistentTerminalProcess and move terminal and environmentVariable files from workbench -> platform
e9b69cd2732 update distro
15b6534a114 file watcher: show info when start watching
67dda13a3ae Move pty to shared process
461bd165ecd IIPCOptions: clarify freshExecArgv
474b4ae2d51 ipc client: fork must not inherit --inspect(-brk)=
f9ac40b8066 testing: add 'show in active file'
cac5eba2aa7 fix workspace trust badge priority
585c5cc04b9 remove get*Actions from view pane
37e41cbfc4a Merge branch 'master' into sandy081/settingsSync/align
f57bdeab80e Merge branch 'master' into sandy081/settingsSync/align
3dc8cb1afc8 Add setting to enable/disable returns generation in jsdoc
62cbf21904e update distro
74b6734e49b remove web overrides
78bdc620d5e - disable auto sync when default service changed in web - donot prevent turning off sync
662bc9b4e84 Merge branch 'merogge/localReconnect' into tyriar_megan_reconnect
1abb2d95341 Merge remote-tracking branch 'origin/master' into tyriar/74620_2
49e2e2b1392 show selecting settings sync service as a separate dialog
a025039b4e9 file picker should only reveal files, not folders nor workspaces, fixes https://github.com/microsoft/vscode/issues/116297
20b8e5fddd2 Workspace trust refactoring (#116354)
969910839d9 make NotebookDocumentMetadata and NotebookCellMetadata type-equal with current proposal, https://github.com/microsoft/vscode/issues/116333
08a2af529ed Bring back "debug: select and start" to the command palette
6ed5c53fb7e fix metadata complile error
cf7fc3918f8 remove CellOutputKind type
0e139c697bd allow custom id in NotebookCellOutput
a9f803753c6 Create no accounts menu on demand
19cad54562a actionBar focus: make sure to setFocusable first enabled item
cfa3854c3f4 action bar: only one tab stop
b881f37fccc Merge branch 'master' into notebook/outputs
40b3204d70a some trying for https://github.com/microsoft/vscode/issues/116333
768a68060f1 Change blocking behavior for auth extension activation based on if request is from core or extension, fixes #116295
164e7f8a2ff upgrade DAP to 1.45.0-pre.0
e94d5c78398 use weights instead of when (#116277)
c6da75c9ed5 Show a notification for all detected ports even when they are already forwarded when auto forwarding is enabled Fixes microsoft/vscode-remote-release#4309
c87de4b1f30 Let extension contribute to ports context and return useful info from port label command Part of microsoft/vscode-remote-release#4433
d2a6b516e4f add check box to use insiders settings sync service while switching
95d4184f267 fix https://github.com/microsoft/vscode/issues/115779
60898cfb4c2 more api todos
87aa935c1d0 💄
9ff3bfec449 sandbox - use electron directly and not preload for postMessage calls
f311b19b644 filewatcher: allow to specify path globs for polling
79a0dbb134e 🆙 distro
83f4dfdff12 streams - introduce and adopt listenStream
699cc6abd39 fixes #116036
3e32386a5bb prepare for KernelInfo#supportedLanguages, https://github.com/microsoft/vscode/issues/116314
b24ca32e4bf little prep for https://github.com/microsoft/vscode/issues/116314
2a1a7a887c8 💄
7d9aa94fd84 repl: no need to use toString() for diffIdentity computation
e371faebfb6 rename createChannelReceiver into ProxyChannel namespace (#116308)
ddb659ae0ec fix https://github.com/microsoft/vscode/issues/116094
48e10bedc9e Revert "tryActivateProvider should not blocking"
ea185a2bbba sash: add hover feedback delay
49b21da91be position run-submenu further to the left, https://github.com/microsoft/vscode/issues/114123
194aa7dfd11 set settings sync logger name
f5ac4f42cc2 sandbox - receive message port via postMessage
5f67699d300 Fix color for the info and warning icons
e58a5e897ea cell execution API sketches
3d9f13ea764 fix: CreateFile ERROR_FILE_NOT_FOUND from crashpad handler (#116252)
883b8629451 debt - prevent vs/code dependency from vs/server
3b456a28573 debt - do not allow platform layer to reach into code layer
facb3703081 🆙 distro
f82462ba7c6 debt - move shellEnv to platform
6c479056158 unknown metadata value.
fe6eb68d228 Pick up latest TS insiders
91a20c06b96 Use npm for building markdown preview
ba7d28d53cd Use shared webpack version instead of installing locally for simple-browser
76524ef5891 Fixes 114236: Add a multi-line comment regex to unIndentedLinePattern (#114478)
b2724146f07 debug: replace element when appending text to ensure updates in repl
90705080760 Merge branch 'connor4312/refactor-test-states'
3d4cabb608f testing: refactor to new runState API
7ecf23a2a2c Try wrapping IPv6 host for webview resource loading with`[]`
8a3a5d9b747 Fix search smoke test
2f76945a065 Relayout search view when message visibility changes #116182
2e9f767776a awaiting-insiders-release => unreleased
64db71fed86 Fixes #116235 - removes inline-flex
60665b5bb71 Removes dead code
f8cadcc6f35 Fixes #116168 - missing provider == missing icons
2b6e896effb Adds another of my email addresses
41121165b0f Move isAccessAllowed to authentication service
06c8e30c736 did save event listener is not hooked up properly
aa1e745af36 send mimetype specific metadata to webview
ebc23863666 style polish
81c7bddee99 diff editor compare outputs should ignore outputid
87999247963 resize observer does not count padding.
409034368dc [renderer] fix string conversion for numbers
97998b32e9f implment getCellViewModel for side by side diff editor.
7b64e249baa node-pty@0.11.0-beta1
968499cb683 Adjust message, fix icon color
e8d77e425f3 add changes
52457101377 Fix #116188: Search in files not pasting selected text using keyboard shortcut
71e56891549 tryActivateProvider should not blocking
eddf95f0893 off by one...
68ec717149c Move extension icon color to a theme color token (refs #115799)
758fe86b54f Fix account badge update for new session requests
11b885de68b Merge remote-tracking branch 'origin/master' into notebook/outputs
a05c4170f6f do not render if there is no mimetype at all.
538c7847c8e Revert "notebook diff editor handle empty mimetypes."
e02e9687889 fix notebook worker dto
acaf2ed2ac8 fix tests
478a76a1a6f fix compilation
16bd4632051 fix compilation issue
97fde37887b - introduce trusted api - disable settings sync in untrusted workspace
78446fc7950 Improve guidance commentary in GH Bug Report template (#116183)
7cb0840ad7d update distro
accae732939 Merge pull request #116051 from microsoft/sandy081/sandbox/spdlog
327e25fdc26 Add portsAttributes to devcontainer.json Part of microsoft/vscode-remote-release#4445
624f51c0f7e debug console: diff identity provider should take the string content into account when computing ids
7fd4b1187cd Fix #116108
efd5a000c0b add InlineHintKind to InlineHint-type
8077bf32517 Fix iconLabel hover hide on click Part of #116197
615d2fff058 fixes #116155
79a623d9767 move to sandbox
5d1e300546e Missing info from the "Recent Workspaces and Folders" section in the taskbar context menu. Fixes #115898
065e82d8624 fix layering
b14afd09df3 Merge branch 'master' into sandy081/sandbox/spdlog
a8bb42c43b0 #116112 remove dependency on IActionViewItem
97c7d2ac84b add `editor/title/run` menu id and expose as proposed API
9b6aafb692d Improve trace messages
b784c952088 Remove terminalFocus from create new term keybinding
992481db7f1 "inline" empty submenus in editor title bar
ffe7654a9f7 ts - no implicit any
49061a5b8a1 Only show port notification in last window Part of #116058
d1c5afbbdcf Fix changing drives in simple file picker
f2f9d1b1e01 Merge remote-tracking branch 'origin/master' into tyriar/74620_2
1e8edfea6ed shared process - move all settings sync related services to sandbox
8116b47d82c sandbox - move user data sync contrib to sandbox
eb777f064b5 sandbox - move extension management and tips to sandbox
08988e65b5c sandbox - move telemetry service to electron-sandbox
b6545a0db66 windows does not support symbolic links
3a3b42a9a3a Merge remote-tracking branch 'origin/master' into tyriar/74620_2
4b5108a79b8 Remove log
47adc864f89 Get 2 way communication working
6132a763bc8 Get one way communication happening
6b030798796 only ask to inline when there would be enough space, https://github.com/microsoft/vscode/issues/114123
4941e47c025 add support to automatically inlining submenus (when rendering), adopt in editor titles for the len(submenu)=1 case
34adb675130 improve hover feedback for sash corners
3ef4aa861a3 sandbox - move localizations service to sandbox
9c40b34cbee sandbox - move diagnostics service to electron sandbox
9441f9054f7 shared process - move service to electron-sandbox
8c8ab33b79d shared process - delete sharedIPCHandle
6ac77de5d74 pfs - improve symbolic link test for windows
e5823fed988 :chore: extra comment
7e923e6f6ee action2 in explorer and debug: make sure to use original to preserve english title in command palette
0795762a8f0 allow gear~spin
100b7f04506 status - update background color (#115886)
82c57ad1fe4 name and id are required for remote views Fixes
c7427d59b11 always fallback to plain text (#115860)
bc1aac2a828 Dedupe tunnel requests for localhost Fixes #116124
2678e4b848a Only match exactly 7 equals (fixes #95040)
cd97629c445 #116152 enable smoke tests
714fd96f61a #114901 revert partially - do not scope view pane container context to its domnode - only use target while creating the menu actions
65505d8bec5 Merge pull request #115599 from microsoft/ben/114753
be5126d37c3 Also skip 'before', #116156
0829608afbf Change disabled tests to .skip
87a3effc79a Try to disable caching in the simple browser's iframes
518097377de Handle 304s for remote resources
99f4a0262ed notebook diff editor handle empty mimetypes.
d94093a14e6 handle append/replace output items.
29844a0baf3 disable smoke tests that time out
4623a509954 Fix #116154
6ba6002fb56 builtin renderer handles OutputItem.
fd6997fdc72 new output type shape only.
bd47ac847c3 auto save ...
779938d5e45 fix outputs loading
64a164c9d5c Add default color for sash hover border color (refs #114636)
ff03697a1aa Use node script instead of 'cp' command
0544c1d391c remove legacy typings.
46e28e3bbea Copy codicon files directly into sources instead of taking a non dev dependecy on the entire package
5b32b280375 Mark simple browser as a UI extension
eb62ecb01e2 Use white background in simple browser by default
b06d9007ef4 chore: bump electron@11.2.3
4e0bc11ad3f relative sizes persist
b7882a858fa touch up
7dc31b45ba0 active instance working for each tab
15616c18692 focused view context key should be set at global context
1e298d0353e Pass executableEnv to other side
456841a93ba Create createProcess ipc interface
281d2280861 Rename pty service to local pty service
c7d527f9cec update yarn.lock
280cbff391c fix home menu items not appearing
ee4a8bd5f4a Create pty service main <-> renderer channel
3021226eefd Move remoteterminalservice reg to contribution
4c690b34e09 remove log statement
9fc381f258c persist local terminals - not yet setting active instance or relative sizes
e146dd28e12 Extension management - refactoring workspace trust signal (#116118)
783bb42362b testing: adopt new state icons
3edc9925e05 NotebookDocument#metadata is readonly
c86be3bb57c Merge pull request #115309 from pfitzseb/sp/julia-grammar
5cfa6b7e263 update vscode-grammar-updater
a873e60a71b 💄 strict assertions
3334b1534c9 #114901 associate scoped context key service to target
86701b150d2 debug: update js-debug
fb8bced55bd after fix for grammar importer
0293b129e37 add name attribute, https://github.com/microsoft/vscode/issues/115746
7f1d17baca2 Update gulp-atom-electron (#116119)
1a9635193f6 update and fix grammar
ebac2cfa10b add colorizer test
50dc6c3c66f add search support
ac7918ed6e2 Fix terminal paste command
1da95321b14 RPM: Don't generate build_id links (#116105)
f5381197bf7 Improve ports view welcome text Part of #116058
0f170017904 Fix update-grammar scripts for cross-platform use
01ace15b27b Fix clear terminal command ID
3fa2ca3f7b0 Fix new terminal keybinding
2a38ef15feb remove used code
124cd2155a2 Merge branch 'master' into pr/pfitzseb/115309
75f4a581b7a fix https://github.com/microsoft/vscode/issues/116104
82f3379ac67 remove getActions*2 from view pane container
9dd25c4d196 Don't show browser preview action in Ports view web Part of microsoft/vscode-remote-release#4436
809bbd7b62f move interface to its sole user
67bac9bf500 remove unused types
e3d0d9c00cf Merge branch 'master' into notebook/outputs
d0205792b0e add todo-tags for API feedback
83a2eb403e1 fix compile errors
99c1589aed3 Merge pull request #116005 from jeanp413/fix-115922
4821adfc12d move convert logic into extHostTypeConverters
599f7a7031b logger shall log always when created with always option
2baf63ad001 use logger service for output appenders
f891543df7d Properly check for FuzzyScore.Default value. This was a regression from 37a4b96ae1820d21d215b460006e0baab471d6cc
afd102cbd2e Trusted Workspaces Feature Branch Merge (#115961)
01a3787cca0 Remove 'grant access' badge when done, fixes #115950
659245f86ca append or replace mimetypes.
03fdd53f968 append/replace output items
7323c520847 testing: avoid showing 100% if any test failed
ac60c82c7d7 add tests (#115944)
008e5c73371 RenderType.mainframe
90327ba10fd rename.
9f4772a98f1 rich mimetype renderer refactor
fc336c97d97 allow \closedWith comment to add unreleaded label itself
3c6756c11c9 Remove unused trigger
cfaf161c497 Bump actions (for the last time! moving to `stable` branch vs release tags)
5024a7053a0 convert output exthost/main. not optimized.
d68691c4445 fix  #115931
152ccfbf3ab Update .mailmap
125bbba18dd Add self to mailmap
686f84aacf3 Fix typo
bdd51f1a048 Add name to mailmap
6302319a4ab Fix Emmet yarn lock
acb1bfa51c6 Update distro
cd725da2b22 xterm@4.11.0-beta.3
4fc8dc82f35 Fixes #110496 - use builtin gestures for open/diff
0a972947a13 no error and stream output anymore
3c17b03d3d1 💄
175ac0e0e53 OutputDto always has id
a3ef2648025 internal output types always have id
392128e1fe5 enable diff decorations first.
339d6ddf183 Fix #115854, #115839
ae0cfa4ec4c fixes #115810
9ec337bb49c BreadcrumbsControl#update should know when something changed, https://github.com/microsoft/vscode/issues/112630
c11bf9d7dfd register open explorer command with container
e60bc310b8e move window logging to main
e136ed66fd3 todo-comment update
70d355c42fa Fixes #115786: Handle overlapping semantic tokens
26e6d9e93ad Set the remote ext host pid and name (#115891)
c88888aa9bc wip: support overlay context key service
46c91d443a1 Update distro
80a738c2ffa Merge pull request #115758 from microsoft/tyriar/115053
daf7dd408b8 appFolder -> execInstallFolder
6b3d7512061 Merge pull request #114566 from microsoft/tyriar/92038
6848fcd7b0c Merge remote-tracking branch 'origin/master' into tyriar/115053
a4a6607ceb0 Use weak shell quoting for npm tasks with -- Part of #115876
631cc755d64 Resolve some todos
b3a0d081aea add deprecation tags,  remove unreferenced types, add more todos
3c7fc6d6a0d fix unused import
d33b89256ea [css][html] Option to disable MDN Reference popups only (without effecting other functionalities). Fixes #97979
1b4a9029355 Revert "remove used dto interfaces"
8522c22cb4f remove used dto interfaces
6f936f91fb0 remove need to massage ids onto output items
8737b166361 💄
bfa8e4e4005 Merge remote-tracking branch 'origin/master' into tyriar/92038
c54fb3c0d16 Fix remove recent task causing configure to run Fixes #114679
251e3e6ee33 Improve port hover Fixes microsoft/vscode-internalbacklog#1757
06e002eb16a Avoid deprecated assert methods
20f3ece2e09 Handle input on Android Fixes microsoft/vscode#107524 Fixes microsoft/monaco-editor#48 Fixes microsoft/monaco-editor#528 Fixes microsoft/monaco-editor#562 Fixes microsoft/monaco-editor#563 Fixes microsoft/monaco-editor#1538 Fixes microsoft/monaco-editor#2261 Refs microsoft/vscode#107602
6558f865330 `self.trustedTypes.createPolicy` is undefined in web workers on Android
7e25b47e662 Merge pull request #115809 from ferenczy/bugfix/wordBasedSuggestionsMode-typo
f3fd96e0f9f add NotebookCell#output2
0b4c2d48dc1 update distro
587ebc5d2ee Fix: wrong event for `onDidSaveNotebookDocument`
a9b412330a4 remote cli: open URL: %2F  lost. Fixes microsoft/vscode-remote-release#4421
cdc8628d55e rename log service to logger
cf0b1a89265 debug: when focusing sessions from drop down give priority to stopped sessions
77bbee524f9 make extHost only send ITransformedDisplayOutputDto (convert error, text output inside the ext host)
cbc01b9a7b4 Don't leak RPC objects from API (#115679)
70cd3b36bac fix yarn lock changes names
84c635738d0 naming
a059d1deae8 more API proposals
e9c65a7e625 Supplementary function parameter types
17e0b26a858 Supplementary function parameter types
52838cf6799 Add back logging to open service.
dae51e3d5eb Revert "Fix build.."
28bd11549a4 Fix build..
a53084475d9 Add logging to help daignose. github/codespaces#2248
a7fbb92962d Revert "Revert "Don't modify _resolvedUriTargets after first set.""
f5f040052c2 Revert "Don't modify _resolvedUriTargets after first set."
2ff5b909bac fix smoke test typings.
0df177fe393 fix tests.
b84cadf3f83 Don't modify _resolvedUriTargets after first set. Maybe a fix for github/codespaces#2248
8c1c32be6d4 Update commonEditorConfig.ts
f2b87fd6cd4 Extensions do not update cell outputs/metadata directly.
99f71a032ea tweak settings for macos web
4d6d2266fac reuse display output as the single output type for rendering
12eb0b72541 updating web menu behavior refs #114200
2fda718ad71 Fixes #115801 - improves conflict decorations
916c13921dc onload => addDisposableListener Ref #115325
28b81efa20f Move configure terminal settings to registerAction2
b32502b95c0 Add terminal view item to view file
98f697844a3 Make switch terminal action use registerAction2
193173c8289 Fixes #114361 - adds branch/repo to aria label
c30770a4256 Hide copy when no selection (disable would be ideal)
b751e8a137c Select default shell
bead496a613 Use object-fit: contain to keep image at proper aspect ratio. Ref #115325
beee6b13f7e Split terminal in active workspace
4dfab617e0b Merge branch 'sandy081/smoketests/remote'
63310d91d3c remove install extension
698eea649ea Remove editor from preview on interction.
a0855b30c70 Use rmdirSync instead of rimraf
a81dd8df862 IRawOutput -> IOutputDto
9db9edc09e0 Paste getAction
b5ba200088a output always contains id
6826c825d8a Compress images (ref #115327)
464492ff0bc Terminal getActions: Create terminal
b90b70e7e30 Scale images down under assumption they're exported at 1.5x Closes #115325.
5838880151b Allow for dark/light/hc imges. Closes #115327.
1c60676ac69 Terminal getActions: Kill terminal
c023260cc7c rename menubar visibility default to classic refs #114200
8132711922b Fill in context menu more
fd2ce701b69 testing: fix locale string
5b2dc0cad22 npm: move debug script lens into npm, clean up parsing logic
05b3f6f7adf re #115717
01406096de1 remove unused self size monitoring.
66415d85066 Merge pull request #115775 from microsoft/merogge/terminalUnitTest
5e27d3966dc fix #79692, re-enable test
087b0081983 debug: store debugUx state key to reduce flashing
668a6401f60 build - increase timeout for integration tests to 10min
6e3d5182253 Add context menu copy back
7c0be00b979 only update terminal dropdown options if they've changed (#115720)
e88863d191f polish task name message in debug anyway dialog
424b2212e00 debug: propose to debuAnyway if the problemMatcher is not defined
7804da86f09 Update Codicons: add 'git-pull-request-create' 686357b717
62ce116f106 Terminal getActions: Select all
a9bc2be6ce4 Terminal getActions: Copy selection
e9a9a479810 fixes #114914
422361234ff fs - still return child even if unknown (#115645)
190733e9d32 more API todos, NotebookCellOutput#id
116f8f61e1f Merge remote-tracking branch 'origin/master' into tyriar/92038
3973012a9cd Only getPackageManager once per folder Part of #115384
f6581675046 Rename appDirname -> appFolder
3bd244bcf25 Merge branch 'master' into sandy081/smoketests/remote
900f1a1c5f6 iconExtensionPoint: improve descriptions and nls keys
52ecf853209 Check for drive letter without slash in file picker Fixes #114567
2d10baa51af remove NotebookCellOutput#metadata
e83180b96f2 Merge branch 'joao/scm-menu-actions'
3421442c963 💄
42cdb7fa0b5 fixes #115677
684f61b4567 Allow to contribute to icon registry from icon contribution point. Fixes #114942
082af46e665 base icon regexes on shared expressions
ab43469e12b Use role 'none' for some parts to make screen readers less chatty
c178440297c update distro
94bc75db66d Merge branch 'master' into sandy081/smoketests/remote
a54d8b23c13 fixes #114908
4afd8c709c8 Catch expected exception in tree view test Fixes #113896
056d6609183 Merge branch 'master' into sandy081/smoketests/remote
a93d3178841 update package json
cb537dd4e82 fs - provide a fallback when readdir with filetypes fails (#115645)
be820b8f425 Fix custom iconLabel hover flickering on description Fixes #114230
2b6bd236136 Fix #115690
70d9246943b fs - use our readdir method everywhere
d4b65868f2d enable the test
0494790a5ee fix https://github.com/microsoft/vscode/issues/115746
9572b419cbd test not running - enable remote check
2c00f1afc97 Add validation message for portsAttributes Fixes microsoft/vscode-remote-release#4365
72e8e9f5bef fs - do not log an error when watching results in ENOENT
914cef30d50 integration tests - disable minimap to reduce error output (#115747)
bd20a720fba Rename "Existing Tunnels"
3c3686e0fbc check only extension
66a1a9bee37 fs - 💄 symbolic links handling
6250b9fde91 🆙 distro
30ba42cf462 fs - fix leftover todo
0eb2d4556a2 Modernize pfs file system library (#115695)
4bdba123d24 use PersistKeySet
265d5da0b34 remove unused buildunit-files, fyi @dbaeumer
d62c307366e fs - fix tests on windows
55ab8b53f80 Merge branch 'master' into sandy081/smoketests/remote
acedbdf50b1 update distro
0ecd7f72d8e add remote server cli test
a0d9df38adf Merge remote-tracking branch 'origin/master' into joao/scm-menu-actions
f4581645226 fs - add test for symbolic link handling when link points to source
ba35190e9cc limit editor title bar actions to 7 entries, https://github.com/microsoft/vscode/issues/115198
866c0160d47 fix build.
43beff622ac 💄
55d04df641d Fix #115316: Getting started back button looks unstyled
9ddea6f385e chore: bump electron@11.2.2
041f9b975b0 fix missing total height change event.
e984154e118 merge stream output in rendering
5d650cd8178 Allow setting startupEditor to `readme` as either default value or user value. Fix github/codespaces#1580
370a7ee077d Don't show a modal on 'getSession' for access requests if 'createIfNone' is false, fixes #111529
a9ccd48a1f7 enable extension tests in web
d6ebd887f73 Merge branch 'master' into ben/modernize-fs
bc0645202f3 fix build.
eac031eedd7 💄
46c10294642 Fix #115316: Getting started back button looks unstyled
ff85144fdd3 chore: bump electron@11.2.2
4e6d9ce2b79 add server cli test
cc58f84bfef Merge branch 'rebornix/stream-output'
cda6949fedd scm: hide actions when no repos are open
9c479a4518d enable remote smoke tests
2402c94e8ea scm: collapse all menu item
4beba243a03 fix missing total height change event.
6931bc71320 merge stream output in rendering
acc0d4206e1 💄
d2eaafb9078 scm: sort actions
3842f92113a scm menus: RepositoryVisibilityAction.precondition
ff7921ebd13 Allow setting startupEditor to `readme` as either default value or user value. Fix github/codespaces#1580
066c5844050 enable remote smoke tests
5115a8eae79 Don't show a modal on 'getSession' for access requests if 'createIfNone' is false, fixes #111529
55579f367af update distro
caca11f2997 Bump Emmet to fix #115623
1925f5ce16c xterm@4.11.0-beta.2
ef0657580f9 fs - preserve symlinks properly
59cf8810d92 Remove min-height from input box message Looks like the 34 here is just an old leftover
f7ffeda190d scm menus: RepositoryVisibilityActionController
9dbc765a385 Add appDirname variable
dfc2a6c1ae2 Fix codicon tree action vertical alignment
2d31774a528 fs - provide an option to `copy` to preserve symlinks or not
056418cb9f8 Improve portsAttributes setting description Fixes microsoft/vscode-remote-release#4373
268bb6ea737 Scroll input right when setting selection at end Fixes #115152
c5bf12802f1 Fix #115699
02fddad16d9 scm: more menu refactorings
429f1bae119 fixes #115625
28359b13691 Fixes #115588: Dispose everything associated with the extension host before attempting to close window
45bf35664a9 💄
805d7949eb4 Use relaunch function instead of reuseTerminal
4f237e52bb9 scm menus: view mode toggles
00d81156476 Merge branch 'master' into ben/modernize-fs
a00411c7e8b Debug Console, Copy All (to clipboard) do not include source file name
bab55b86fc5 Merge pull request #114182 from susiwen8/113389
4bc335b05ab Introduce setting debug.console.collapseIdenticalLines to disable collapsing identical lines in Debug Console
376716d1aee status bar - don't leak RPC objects from API (#115679)
538f72e2a7b Fixes #115662: Add support for escaping `@` as `@@` in regular expressions to avoid replacement
26ffdab0be4 Merge branch 'master' into joao/scm-menu-actions
495ed055117 fs - preserve symlinks when copying them (#114881)
06c0dbe6162 fix compilation error
2525f3e2763 Merge branch 'master' into pr/113673
7c90e1f5ba9 fixes 115685
67ccf8c649e Add open preveiw action to port notification and setting (#114572)
8d7157ed451 Make task definitions dynamic Fixes #114793
1cab95f5b6c fs - fix compile error for now
aca5d3ea2e9 fs - merge readdir functions into one
7e05f9f0821 add appendCellOutput API proposal and implementation
aaf7b923c6c fix: prevent scroll when list focused in zone-widget (#114912)
6675687f9e2 Merge branch 'joao/fix-100151'
03fd1a32c0f 💄
73c5b484f34 fixes #100151
b28cd23d521 fs - more removal of promisify utility
6ca7afa84fb add support for `application/x.notebook.error-traceback` mime type
dbf6147c01e fs - remove promise based methods from pfs and replace with fs.promises
42436d5a7be Merge pull request #115665 from microsoft/ben/113703
a17c656c330 fs - some polish around file services
a01d16e77e9 debt - use a native private property in ExtHostQuickInput
194e1c5f1c8 fs - retry async rimraf unlink
e2f7159745c fs - remove custom rimraf solutions
c399d039a71 debt - don't expose MainThreadNotebookShape from NotebookEditorDecorationType
60ce9ab9c5a #115590 More tweaks
74937e0a89b Merge pull request #115530 from microsoft/joh/norpc
944c4b4fced fs - drop our custom rimraf solution and use node.js
2cf80f97cc1 Azure DevOps - Add global variable for VSCODE_QUALITY (#115636)
aa840d53d28 Move action microsoft/vscode-github-triage-actions
e99ec0c6e54 do not register open command for generated view containers
7690293ae20 clean up and add some doc
5b913c0cc21 Merge branch 'master' into ben/modernize-fs
ef1f94d969b "Select for Compare" is available for WebView tabs (fix #113703)
63ad2bafafa Fix #115321: Getting started Skip button does not use pointer cursor and has really wide click target
b7e588f2c64 Fix #115322: Getting started "Next" button in step is not keyboard accessible
4f8637eb541 Dont contract item on reload
bcf14260d2d Make sure contibuted openers are cleaned up if they are renamed for an extension that is not uninstalled
34e46f2e67d Support anyOf for rich settings editor (#115648)
51e6c241d1b Change click on selected item to deselect it.
a9e6b93132e Fix #115393
5f3c37f918d fix #115099
82812ed8c93 Treat clicks on the image the same as clicks on the button. Fixes #115320
316a1d86e09 Enable rich settings object editor for schemas that use anyOf (#115642)
352d5df7728 Mark functions abstract for settings tree (#115643)
617095939f4 Fix #115323: Getting started pressing enter when when the step has focus does nothing
dfe10d0baf5 Get started color polish (#115331)
a105ccb4363 #115289 fix show explorer command
cba8232d778 update seti & add preview page
570f46ddf20 #115289 - register view open action - use view open action id if view container open action is not registered - do not register view container open action for panels and some viewlets
ef64c83ef29 Fix #115429: Search keyword is cleared after window reload
01216213efa improve terminal title sanitizing, fix #115291 (#115634)
a881dd44ccd support running active files with filenames containing parenthesis (#114946)
66635b8bd6e remove unknown content change in nb text model.
acb300b004b Merge pull request #115630 from microsoft/rebornix/multi-selection
5d84ee5c192 Ensures icons are contained
06fc252b9a4 Prioritize import quickfix over spelling
501274f1d7a Fix #115633
04abcc03381 yarn watchd does not detect interface change again.
16d84195625 smoke test
5ec17aba95e fix build in exthostnotebook
04e6c8638ec Prevent decoding URI the user is trying to open externally (#115615)
3c79b84e34c Update Codicons: add type hierarchy, table, and variable-group icons 6e29ef1dae 39a2dd5bba
57488b54303 Fix #115595: Search editor: respect `soft` option in `revert`
4aa4d1f65f7 Revert "Add a dialog box when opening unsaved files in a custom editor (#114947)" (#115627)
33f49b2363c Add a dialog box when opening unsaved files in a custom editor (#114947)
c3c0db94f3d Merge remote-tracking branch 'origin' into rebornix/multi-selection
c4f273e3dfe fix tests.
9c4d2480630 fs - avoid one exists() call
0677d5e6f62 fs - sort pfs and introduce SymlinkSupport namespace
3088c27fbdc debug: mark terminal as free when the associated debug session ends (#115573)
6662709200d Merge pull request #115578 from obsgolem/master
e6712df1110 Simplify logic
b60478452fa [themes] fix dept in default theme files. Fixes  #111877
f345c732a3e Allow moving to blank lines also by model lines
7a6a45fb2c1 browser tests - fix regression from updating playwright
76e6174c90b validate yarn.lock changes in PRs
3c6e1758ecf Convert to use PrevBlankLine / NextBlankLine in the "to" argument.
2808625686b No need to create aliases
1a016a67b2e 🆙 deps
d50306793fc Upgrade Playwright to v1.8.0.  (#115241)
507e210014e Sentence casing on terminal link text Fixes microsoft/vscode-remote-release#4363
970d920f5bd fs - modernize `move` and add comments
3debe292293 #115590 tweak wordings
21aa14f0642 remove ext.ts
653e409f480 Merge pull request #115336 from rluvaton/patch-1
085185259ff Env var changes will restart terminal automatically
fd978d6feac Merge pull request #115190 from PathToLife/pathtolife/double-press-keybind
b8737236efd Minor tweaks
3022afaeaa2 Minor refactorings
2fb57aa3b64 Revert do not show compare for markdown preivew
a0d76bb9834 fs - drop pfs.mkdirp in favor of node.js
ca746af08ab fix hygiene
35e1ee2ecc0 ext: extract to disk
72a9a9ca395 Simplify code
3079c2245ce Only restore non-auto-forwarded ports Fixes #115216
a77a89eaef4 Also handle single modifier keybindings in `StandaloneKeybindingService`
cfc22176e62 Add tests, some renames & refactorings
7e714f4d25e more notebook API todos
c3b556727e2 fix update-grammars script
8bf9b56adec Merge branch 'joao/extensions'
fa0e0004772 💄
f92b41b5d5e Add defaultSnippets for portsAttributes Fixes microsoft/vscode-remote-release#4382
7e0230677aa improve ext ci output
c770c381978 update notebook milestones
9dcecc01c6f fix https://github.com/microsoft/vscode/issues/115353
6b2a14afc68 Prevent two task defaults Fixes #115281
56dfaf8b985 #115522 adopt to settled promises
b2d303d16e7 ext: allow anonymous access
42fcb8d7c55 Custom editors: improve the generic save error notification (fix #115598)
abb05eb058b Fix #115586
83935a961f0 Merge pull request #115452 from jogo-/patch-1
7020ccf1346 #115289 show only default containers in view menu
3feb8937a80 editors - make sure to always remove pending confirmations even in error case
4342faa67cf backup tracker - wire in cancellation token
867b60d649e backups - show cancellable progress for backup/revert too (#115028)
04d4310a8a5 fix smoketest (#115586)
2604a356e27 Fix typo in papercuts.github-issues
ee29ad444b7 Include closed issues too for verification found.
d45a8915d27 transient metadata should be used to control the content change and dirty state.
f96b651052a we should only use comm object to communicate.
36e0c46923e Merge branch 'master' into rebornix/multi-selection
be9de77eb40 Added a new "blankLine" option for move units. This option will move the cursor to the next/previous line which consists only of whitespace, skipping over folded or otherwise hidden lines.
d9ff550d02d Add intellisense for onOpenExternalUri activation and rename event
7d5052f5084 Set permission handlers for webviews
d99c218e9b2 Make sure we always apply TS auto imports, even if VS Code applies the completion before it has been resolved
60bb22ddd3c Use `test` instead of `match`
7490ac87e19 Fix spelling
5851bcab4d9 Use `?.`
c3699dc01db Fix wording on error
4ccfa1d019b Fix spelling
6f1fbfdd935 Inline object map type
8c3e6cd9ee2 Fix spelling
4e00f75408e Remove stubs file reference protocol
6fed1b63833 Uses background flag for better perf/mem usage Filters out deleted resources
ed410a1cc04 adopt icon descriptions fixes from vscode-docs
925d9234b86 Pick up latest TypeScript 4.2 nightly
833bae4fd91 Add more explicit implementations of ICustomEditorInputFactory
0f9ff35c82a Fix #115289
61decba0335 fix extension categories sort order
efaceb5f682 Enable 'Install Additional Product Icon Themes'
82af67ebce4 Plumb etags through rest of the webview resource pipeline (#115360)
80ba07df03b notebooks: add generic colors for renderers (#109412)
d5685965c5e Fix keybinding for Search view missing from view and sidebar #115556
0eaf57957fb typeahead: line wrap improvements
7583817a12a added unreleased fixes to endgame notebook
a5a33501be1 chore - group notebook specific api proposals together
b37252c1823 Update grammars
a99dd66f0f7 test more results of create-functions
02d28757e88 💄
76962b2583a ext: ci command
2ceeaeb6814 hide proxy from TextEditorDecorationType
abbc2e305d7 more API todos for notebooks
c9a7425b903 Merge branch 'master' into pathtolife/double-press-keybind
750888c4967 Merge pull request #114957 from TacticalDan/tacticaldan/scrollingPerformance
b82933a1d2a Limit to 8ms (120fps)
0ac7f0ee830 Merge branch 'master' into tacticaldan/scrollingPerformance
3ec92ad8ad5 Better hiding of custom hover in icon label
a5b078b5514 debt - adopt some ? operator
bc837b7162e 💄 dialog main service locks
a0c75f60530 add tests for createXYZ functions and skip most of them...
38ca4695d10 Fix #114432: Multiple save dialogs appearing on Windows if Ctrl+S is pressed multiple times (#114450)
178e7034bc4 simplify map creation, fyi @bpasero
03da2de889c add proper yarn.lock files
a0cb5c5a46e Fix port label not always getting set Part of microsoft/vscode-remote-release#4364
ad8f7e18728 Fixes microsoft/monaco-editor#2329: Move `registerThemingParticipant` call to `/editor/`
38db1778aa1 adopt built-in extensions
b24036eaa27 Use label as tooltip fallback properly Part of #115337
2681e07db46 more notebook todos
53ae79d62d9 Avoid the CSS general sibling combinator ~ for perf reasons
ddd678ab297 debug console menu action polish
f37f96bbec3 Merge pull request #115261 from microsoft/alex/language-config-priority
47390dbe1b1 Fixes #115221: update emoji tests
300effb0c8f add some notebook API todos
3d2ca29012c hide terminal proxy
a60beb9d7a8 don't leak proxies in editor land, also remove indentSize property which isn't API
82c629eb3a4 hide tasks in TaskExecution
46cf57b2646 a bunch of failing tests
930b5686ffa add todo
3114b1c4c52 hide rpc proxies
4cfd5f85080 clipboard changes
1ecf01b9c71 mark rpc protocol and proxies with symbols and try to find them from an API test (with success...)
01e92bdc93c debug: do not render checkmark in view menu for the debug console
b08c1eb5bce Merge pull request #115345 from shskwmt/fix/115154
1f4506183c4 for now remove isSaving() implementation from custom editors (#115526)
34ca1211023 adopt Promises.settled
00a199daf73 Merge branch 'master' into fix/115154
8b510618c89 Merge pull request #115401 from microsoft/tyriar/115390
0627cf0a2d2 event - adopt Promises.settled in async emitter (#115522)
769ad06e7c1 Promise.allSettled - use native variant if it exists
71bd9c5032c Revert "event - adopt Promises.settled in async emitter (#115522)"
643cbb2aaa6 Fixes microsoft/monaco-editor#2328: In some webpack configurations, `process` can be defined, while `process.nextTick` is not
126959896ff event - adopt Promises.settled in async emitter (#115522)
5c7fc5da28e Fixes #112382: Use replacement characters when doing dom based line break computin
c2759462f8b backups - catch errors on shutdown and don't show modal dialogs in extension development (#115028)
0ca20779b5b Promise.all() does not await all promises when one throws (#115522)
08c73d7b6e4 history - make sure to track file renames properly (#113277)
8d6164f25d1 🆙 chokidar@3.5.1
d30c12dc6b3 debt - fix some types in bootstrap JS files
a9b98904880 Improving performance of tree traversal getViewState function (#115387)
f5bb67e37aa Unit tests cleanup (#115377)
6a1c7a5097d Fix #115509, register a separate action for opening serch editor from view
9e152f9a193 Fix #11511 Search Mode setting does not open editors unless search view is visible
50ec8ea6e76 Merge branch 'master' into patch-1
ef2c97e92f6 Fix spelling in papercuts.github-issues
a916ce9076c Add "overflow: hidden" style to split-view-view within integrated-terminal
81ae94a9dc8 bump version to 1.54.0
ec805db5eda add repository field to extensions package.json
9a5d14e307a run prettier over extensions json files
1e8d0be3761 Make term config tests await config
3921d63e64f Add "overflow: hidden" style to split-view-view
c628fd10fb0 Merge branch 'master' into patch-1
80f20b3d9f2 fix(workbench): add forgotten escaping in regex
b0ac7e40bbd add Julia grammar
8471235643e Give a higher priority to language configuration set via API call (#114684)
9548fe4af9e bugfix - fix macos not working because scan code was removed - add isModifierKey() logic to scanCode.ts, consistent with windows keyCodes.ts
b14064fbf84 minor commit - fix comment inconsistency - rename function camelCase
d8a474947ce fix comments
de4b1289848 fix PR Layers check
27fc6204873 comments
26c709a7c6a Merge branch 'microsoft-master'
28b3a7e3a93 New method to avoid regression, found via unit test, related to modifier keys being ignored in getDisptachParts()
301b9f7ed77 working on fixing unit test regressions
c67f42f1b51 Fix modifier key triggering chord - revert removal of shift key
4d0d77f9b12 remove attempt at fixing shift+[shiftleft] binding - better solution to be commited later
ae426b39b18 macos implemented double shift keybind windows initial implementation
bc0262a6645 Revert "hack to make double shift possible in widget"
6794401b7c8 minimal changes
5e948799db0 fix build
b2600b23d5b Cut keyboard shortcut support mutli selection
86a88180596 multi selection in notebook
601161f8dd0 Reduce arbitrary event limiter from 16ms down to 4.16666 (support for monitors up-to 240hz) #107016
caac9511a73 windows attempt at "shift shift" - still bugged
5ed3c977bdc hack to make double shift possible in widget
03c59637b69 wip
160bdf06b34 wip: adopt menu actions in scm
768ace7b7f1 Merge branch 'master' into 113389
9be03fe29b2 Fix: add alwaysConsumeMouseWheel for list
3563e2b7403 rename run to exec for consistency
REVERT: 622cb03f7e0 Merge pull request #116444 from microsoft/alex/stable-fix-116060
REVERT: 5933e313e5d Fixes #116060: Clone minimap options before changing them
REVERT: f3a12e053e1 Pick up TS 4.1.5 (#116380)
REVERT: 3b9cef2b8d1 Bump Emmet (#116230)
REVERT: 8757f67bcda fix #116049 (#116319)
REVERT: 73c0a56bbd2 Merge pull request #116311 from microsoft/joh/fix/116094
REVERT: 5cf34afa107 Use weak shell quoting for npm tasks with -- (#116309)
REVERT: 6635ca9a64e Merge pull request #116245 from microsoft/connor4312/debug-repl-fix
REVERT: 65406fcea58 fix https://github.com/microsoft/vscode/issues/116094
REVERT: 43e11faf4ee fix: CreateFile ERROR_FILE_NOT_FOUND from crashpad handler (#116256)
REVERT: 17d65083f6c debug: replace element when appending text to ensure updates in repl
REVERT: 9d194eac0d7 This reverts us to the previous distro commit (#116218)
REVERT: 1fe57f42761 Merge pull request #115789 from microsoft/rebornix/fix-notebook-runstate
REVERT: d63ab6acdbd bump version to 1.53.2 (#116228)
REVERT: 4aff7304539 Merge pull request #115772 from microsoft/misolori/1.53/create-pr-icon
REVERT: 678843ff3ad fixes #115810 (#115943)
REVERT: e1ec11f5183 always fallback to plain text (#115860) (#116177)
REVERT: 615ea78d96a status - update background color (#115886) (#116181)
REVERT: 00d7f953055 add changes (#116223)
REVERT: 3c19fc731cb Pick up the official TS 4.1.4 build (#116222)
REVERT: 5d424b828ad Pick up new distro version and bump version (#116149)
REVERT: ee2c947e064 ci: update newer 11.2.1 for CVE-2021-21148 (#115951)
REVERT: e23884b9476 re #115717
REVERT: 5da053f081f Update Codicons: add 'git-pull-request-create' 686357b717
REVERT: 7f04ecd68be use PersistKeySet (#115744)
REVERT: 8490d3dde47 Merge pull request #115701 from microsoft/sandy081/fix115699
REVERT: 1d6c8826375 Fix #115699
REVERT: f84decb78f3 Merge pull request #115686 from microsoft/isidorn/openEditorsCollapsed
REVERT: 203b86d14c5 fixes 115685
REVERT: 83f7a99bd95 Azure DevOps - Add global variable for VSCODE_QUALITY (#115636) (#115673)
REVERT: e1c818a1711 Merge pull request #115655 from microsoft/rebornix/fix-jupyter-activation
REVERT: 761dd469c13 chore: bump distro
REVERT: 8d779a4fada Merge pull request #115609 from microsoft/joh/fix115353
REVERT: 30fe91131c9 Merge pull request #115611 from microsoft/isidorn/selectForCompareUntitled
REVERT: 8dbf3d717b2 Revert do not show compare for markdown preivew
REVERT: bc38ed1b5a3 fix https://github.com/microsoft/vscode/issues/115353
REVERT: 65006668d07 Merge pull request #115547 from microsoft/aeschli/installProductIconTheme
REVERT: b99487f4168 Fix keybinding for Search view missing from view and sidebar (#115558)
REVERT: feda473d978 Enable 'Install Additional Product Icon Themes'
REVERT: 565dc9704f2 Use label as tooltip fallback properly (#115537)
REVERT: c02643e3c95 Properly set port label from ports attributes
REVERT: ae05392454a Merge pull request #115536 from microsoft/isidorn/debugConsoleCheckmark
REVERT: e4a65573a89 render "Debug Console" action after a separator
REVERT: a62c65bdb74 ignore focus when toggling debug console visibility
REVERT: 4d98741552d debug: do not render checkmark in view menu for the debug console
REVERT: ad232b0ac13 Fix #115509, register a separate action for opening serch editor from view (#115514)
REVERT: 4eb39372949 Fix #115511 Search Mode setting does not open editors unless search view is visible (#115513)

git-subtree-dir: lib/vscode
git-subtree-split: fd6f3bce6709b121a895d042d343d71f317d74e7
This commit is contained in:
Joe Previte
2021-03-11 10:27:09 -07:00
parent 89b6e0164f
commit e8cd17a97d
1459 changed files with 53314 additions and 51110 deletions

13
src/bootstrap.js vendored
View File

@@ -170,6 +170,9 @@
return nlsConfig;
}
/**
* @returns {typeof import('./vs/base/parts/sandbox/electron-sandbox/globals') | undefined}
*/
function safeGlobals() {
const globals = (typeof self === 'object' ? self : typeof global === 'object' ? global : {});
@@ -177,7 +180,7 @@
}
/**
* @returns {NodeJS.Process | undefined}
* @returns {import('./vs/base/parts/sandbox/electron-sandbox/globals').IPartialNodeProcess | NodeJS.Process}
*/
function safeProcess() {
if (typeof process !== 'undefined') {
@@ -188,16 +191,20 @@
if (globals) {
return globals.process; // Native environment (sandboxed)
}
return undefined;
}
/**
* @returns {Electron.IpcRenderer | undefined}
* @returns {import('./vs/base/parts/sandbox/electron-sandbox/electronTypes').IpcRenderer | undefined}
*/
function safeIpcRenderer() {
const globals = safeGlobals();
if (globals) {
return globals.ipcRenderer;
}
return undefined;
}
/**
@@ -236,7 +243,7 @@
}
//#endregion
//#region ApplicationInsights

View File

@@ -9,14 +9,14 @@
const perf = require('./vs/base/common/performance');
perf.mark('code/didStartMain');
const lp = require('./vs/base/node/languagePacks');
const path = require('path');
const fs = require('fs');
const os = require('os');
const { getNLSConfiguration } = require('./vs/base/node/languagePacks');
const bootstrap = require('./bootstrap');
const bootstrapNode = require('./bootstrap-node');
const paths = require('./paths');
/** @type {Partial<import('./vs/platform/product/common/productService').IProductConfiguration> & { applicationName: string}} */
const { getDefaultUserDataPath } = require('./vs/base/node/userDataPath');
/** @type {Partial<import('./vs/platform/product/common/productService').IProductConfiguration>} */
const product = require('../product.json');
const { app, protocol, crashReporter } = require('electron');
@@ -38,70 +38,8 @@ app.setPath('userData', userDataPath);
// Configure static command line arguments
const argvConfig = configureCommandlineSwitchesSync(args);
// If a crash-reporter-directory is specified we store the crash reports
// in the specified directory and don't upload them to the crash server.
let crashReporterDirectory = args['crash-reporter-directory'];
let submitURL = '';
if (crashReporterDirectory) {
crashReporterDirectory = path.normalize(crashReporterDirectory);
if (!path.isAbsolute(crashReporterDirectory)) {
console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory must be absolute.`);
app.exit(1);
}
if (!fs.existsSync(crashReporterDirectory)) {
try {
fs.mkdirSync(crashReporterDirectory);
} catch (error) {
console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory does not seem to exist or cannot be created.`);
app.exit(1);
}
}
// Crashes are stored in the crashDumps directory by default, so we
// need to change that directory to the provided one
console.log(`Found --crash-reporter-directory argument. Setting crashDumps directory to be '${crashReporterDirectory}'`);
app.setPath('crashDumps', crashReporterDirectory);
} else {
const appCenter = product.appCenter;
// Disable Appcenter crash reporting if
// * --crash-reporter-directory is specified
// * enable-crash-reporter runtime argument is set to 'false'
// * --disable-crash-reporter command line parameter is set
if (appCenter && argvConfig['enable-crash-reporter'] && !args['disable-crash-reporter']) {
const isWindows = (process.platform === 'win32');
const isLinux = (process.platform === 'linux');
const crashReporterId = argvConfig['crash-reporter-id'];
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (uuidPattern.test(crashReporterId)) {
submitURL = isWindows ? appCenter[process.arch === 'ia32' ? 'win32-ia32' : 'win32-x64'] : isLinux ? appCenter[`linux-x64`] : appCenter.darwin;
submitURL = submitURL.concat('&uid=', crashReporterId, '&iid=', crashReporterId, '&sid=', crashReporterId);
// Send the id for child node process that are explicitly starting crash reporter.
// For vscode this is ExtensionHost process currently.
const argv = process.argv;
const endOfArgsMarkerIndex = argv.indexOf('--');
if (endOfArgsMarkerIndex === -1) {
argv.push('--crash-reporter-id', crashReporterId);
} else {
// if the we have an argument "--" (end of argument marker)
// we cannot add arguments at the end. rather, we add
// arguments before the "--" marker.
argv.splice(endOfArgsMarkerIndex, 0, '--crash-reporter-id', crashReporterId);
}
}
}
}
// Start crash reporter for all processes
const productName = (product.crashReporter ? product.crashReporter.productName : undefined) || product.nameShort;
const companyName = (product.crashReporter ? product.crashReporter.companyName : undefined) || 'Microsoft';
crashReporter.start({
companyName: companyName,
productName: process.env['VSCODE_DEV'] ? `${productName} Dev` : productName,
submitURL,
uploadToServer: !crashReporterDirectory
});
// Configure crash reporter
configureCrashReporter();
// Set logs path before app 'ready' event if running portable
// to ensure that no 'logs' folder is created on disk at a
@@ -118,29 +56,14 @@ setCurrentWorkingDirectory();
protocol.registerSchemesAsPrivileged([
{
scheme: 'vscode-webview',
privileges: {
standard: true,
secure: true,
supportFetchAPI: true,
corsEnabled: true,
}
privileges: { standard: true, secure: true, supportFetchAPI: true, corsEnabled: true }
}, {
scheme: 'vscode-webview-resource',
privileges: {
secure: true,
standard: true,
supportFetchAPI: true,
corsEnabled: true,
}
privileges: { secure: true, standard: true, supportFetchAPI: true, corsEnabled: true }
},
{
scheme: 'vscode-file',
privileges: {
secure: true,
standard: true,
supportFetchAPI: true,
corsEnabled: true
}
privileges: { secure: true, standard: true, supportFetchAPI: true, corsEnabled: true }
}
]);
@@ -161,7 +84,7 @@ let nlsConfigurationPromise = undefined;
const metaDataFile = path.join(__dirname, 'nls.metadata.json');
const locale = getUserDefinedLocale(argvConfig);
if (locale) {
nlsConfigurationPromise = lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
nlsConfigurationPromise = getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
}
// Load our code once ready
@@ -381,6 +304,106 @@ function getArgvConfigPath() {
return path.join(os.homedir(), dataFolderName, 'argv.json');
}
function configureCrashReporter() {
// If a crash-reporter-directory is specified we store the crash reports
// in the specified directory and don't upload them to the crash server.
let crashReporterDirectory = args['crash-reporter-directory'];
let submitURL = '';
if (crashReporterDirectory) {
crashReporterDirectory = path.normalize(crashReporterDirectory);
if (!path.isAbsolute(crashReporterDirectory)) {
console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory must be absolute.`);
app.exit(1);
}
if (!fs.existsSync(crashReporterDirectory)) {
try {
fs.mkdirSync(crashReporterDirectory);
} catch (error) {
console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory does not seem to exist or cannot be created.`);
app.exit(1);
}
}
// Crashes are stored in the crashDumps directory by default, so we
// need to change that directory to the provided one
console.log(`Found --crash-reporter-directory argument. Setting crashDumps directory to be '${crashReporterDirectory}'`);
app.setPath('crashDumps', crashReporterDirectory);
}
// Otherwise we configure the crash reporter from product.json
else {
const appCenter = product.appCenter;
// Disable Appcenter crash reporting if
// * --crash-reporter-directory is specified
// * enable-crash-reporter runtime argument is set to 'false'
// * --disable-crash-reporter command line parameter is set
if (appCenter && argvConfig['enable-crash-reporter'] && !args['disable-crash-reporter']) {
const isWindows = (process.platform === 'win32');
const isLinux = (process.platform === 'linux');
const isDarwin = (process.platform === 'darwin');
const crashReporterId = argvConfig['crash-reporter-id'];
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (uuidPattern.test(crashReporterId)) {
if (isWindows) {
switch (process.arch) {
case 'ia32':
submitURL = appCenter['win32-ia32'];
break;
case 'x64':
submitURL = appCenter['win32-x64'];
break;
case 'arm64':
submitURL = appCenter['win32-arm64'];
break;
}
} else if (isDarwin) {
if (product.darwinUniversalAssetId) {
submitURL = appCenter['darwin-universal'];
} else {
switch (process.arch) {
case 'x64':
submitURL = appCenter['darwin'];
break;
case 'arm64':
submitURL = appCenter['darwin-arm64'];
break;
}
}
} else if (isLinux) {
submitURL = appCenter['linux-x64'];
}
submitURL = submitURL.concat('&uid=', crashReporterId, '&iid=', crashReporterId, '&sid=', crashReporterId);
// Send the id for child node process that are explicitly starting crash reporter.
// For vscode this is ExtensionHost process currently.
const argv = process.argv;
const endOfArgsMarkerIndex = argv.indexOf('--');
if (endOfArgsMarkerIndex === -1) {
argv.push('--crash-reporter-id', crashReporterId);
} else {
// if the we have an argument "--" (end of argument marker)
// we cannot add arguments at the end. rather, we add
// arguments before the "--" marker.
argv.splice(endOfArgsMarkerIndex, 0, '--crash-reporter-id', crashReporterId);
}
}
}
}
// Start crash reporter for all processes
const productName = (product.crashReporter ? product.crashReporter.productName : undefined) || product.nameShort;
const companyName = (product.crashReporter ? product.crashReporter.companyName : undefined) || 'Microsoft';
crashReporter.start({
companyName: companyName,
productName: process.env['VSCODE_DEV'] ? `${productName} Dev` : productName,
submitURL,
uploadToServer: !crashReporterDirectory,
compress: true
});
}
/**
* @param {import('./vs/platform/environment/common/argv').NativeParsedArgs} cliArgs
* @returns {string | null}
@@ -411,7 +434,7 @@ function getUserDataPath(cliArgs) {
return path.join(portable.portableDataPath, 'user-data');
}
return path.resolve(cliArgs['user-data-dir'] || paths.getDefaultUserDataPath());
return path.resolve(cliArgs['user-data-dir'] || getDefaultUserDataPath());
}
/**
@@ -566,7 +589,7 @@ async function resolveNlsConfiguration() {
// See above the comment about the loader and case sensitiviness
appLocale = appLocale.toLowerCase();
nlsConfiguration = await lp.getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale);
nlsConfiguration = await getNLSConfiguration(product.commit, userDataPath, metaDataFile, appLocale);
if (!nlsConfiguration) {
nlsConfiguration = { locale: appLocale, availableLanguages: {} };
}

View File

@@ -1,48 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
const pkg = require('../package.json');
const path = require('path');
const os = require('os');
/**
* @returns {string}
*/
function getDefaultUserDataPath() {
// Support global VSCODE_APPDATA environment variable
let appDataPath = process.env['VSCODE_APPDATA'];
// Otherwise check per platform
if (!appDataPath) {
switch (process.platform) {
case 'win32':
appDataPath = process.env['APPDATA'];
if (!appDataPath) {
const userProfile = process.env['USERPROFILE'];
if (typeof userProfile !== 'string') {
throw new Error('Windows: Unexpected undefined %USERPROFILE% environment variable');
}
appDataPath = path.join(userProfile, 'AppData', 'Roaming');
}
break;
case 'darwin':
appDataPath = path.join(os.homedir(), 'Library', 'Application Support');
break;
case 'linux':
appDataPath = process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config');
break;
default:
throw new Error('Platform not supported');
}
}
return path.join(appDataPath, pkg.name);
}
exports.getDefaultUserDataPath = getDefaultUserDataPath;

View File

@@ -13,6 +13,12 @@
"sinon",
"winreg",
"trusted-types"
],
"plugins": [
{
"name": "tsec",
"exemptionConfig": "./tsec.exemptions.json"
}
]
},
"include": [

View File

@@ -1,5 +1,31 @@
{
"ban-eval-calls": [
"vs/workbench/api/worker/extHostExtensionService.ts"
],
"ban-function-calls": [
"vs/workbench/api/worker/extHostExtensionService.ts",
"vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts",
"vs/workbench/services/keybinding/test/electron-browser/keyboardMapperTestUtils.ts"
],
"ban-trustedtypes-createpolicy": [
"**/*.ts"
"vs/base/browser/dom.ts",
"vs/base/browser/markdownRenderer.ts",
"vs/base/worker/defaultWorkerFactory.ts",
"vs/base/worker/workerMain.ts",
"vs/editor/browser/core/markdownRenderer.ts",
"vs/editor/browser/view/domLineBreaksComputer.ts",
"vs/editor/browser/view/viewLayer.ts",
"vs/editor/browser/widget/diffEditorWidget.ts",
"vs/editor/browser/widget/diffReview.ts",
"vs/editor/standalone/browser/colorizer.ts",
"vs/workbench/api/worker/extHostExtensionService.ts",
"vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts",
"vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts",
"vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts",
"vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts"
],
"ban-worker-calls": [
"vs/base/worker/defaultWorkerFactory.ts",
"vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts"
]
}

View File

@@ -110,13 +110,13 @@ export const onDidChangeFullscreen = WindowManager.INSTANCE.onDidChangeFullscree
const userAgent = navigator.userAgent;
export const isEdgeLegacy = (userAgent.indexOf('Edge/') >= 0);
export const isFirefox = (userAgent.indexOf('Firefox') >= 0);
export const isWebKit = (userAgent.indexOf('AppleWebKit') >= 0);
export const isChrome = (userAgent.indexOf('Chrome') >= 0);
export const isSafari = (!isChrome && (userAgent.indexOf('Safari') >= 0));
export const isWebkitWebView = (!isChrome && !isSafari && isWebKit);
export const isIPad = (userAgent.indexOf('iPad') >= 0 || (isSafari && navigator.maxTouchPoints > 0));
export const isEdgeLegacyWebView = isEdgeLegacy && (userAgent.indexOf('WebView/') >= 0);
export const isEdgeLegacyWebView = (userAgent.indexOf('Edge/') >= 0) && (userAgent.indexOf('WebView/') >= 0);
export const isElectron = (userAgent.indexOf('Electron/') >= 0);
export const isAndroid = (userAgent.indexOf('Android') >= 0);
export const isStandalone = (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches);

View File

@@ -25,19 +25,7 @@ export const BrowserFeatures = {
readText: (
platform.isNative
|| !!(navigator && navigator.clipboard && navigator.clipboard.readText)
),
richText: (() => {
if (browser.isEdgeLegacy) {
let index = navigator.userAgent.indexOf('Edge/');
let version = parseInt(navigator.userAgent.substring(index + 5, navigator.userAgent.indexOf('.', index)), 10);
if (!version || (version >= 12 && version <= 16)) {
return false;
}
}
return true;
})()
)
},
keyboard: (() => {
if (platform.isNative || browser.isStandalone) {

View File

@@ -3,9 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IAction, IActionRunner, IActionViewItem } from 'vs/base/common/actions';
import { IAction, IActionRunner } from 'vs/base/common/actions';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { AnchorAlignment, AnchorAxisAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
export interface IContextMenuEvent {
readonly shiftKey?: boolean;

View File

@@ -284,7 +284,7 @@ export function modify(callback: () => void): IDisposable {
}
/**
* Add a throttled listener. `handler` is fired at most every 16ms or with the next animation frame (if browser supports it).
* Add a throttled listener. `handler` is fired at most every 8.33333ms or with the next animation frame (if browser supports it).
*/
export interface IEventMerger<R, E> {
(lastEvent: R | null, currentEvent: E): R;
@@ -295,7 +295,7 @@ export interface DOMEvent {
stopPropagation(): void;
}
const MINIMUM_TIME_MS = 16;
const MINIMUM_TIME_MS = 8;
const DEFAULT_EVENT_MERGER: IEventMerger<DOMEvent, DOMEvent> = function (lastEvent: DOMEvent | null, currentEvent: DOMEvent) {
return currentEvent;
};
@@ -841,7 +841,7 @@ export const EventType = {
MOUSE_OUT: 'mouseout',
MOUSE_ENTER: 'mouseenter',
MOUSE_LEAVE: 'mouseleave',
MOUSE_WHEEL: browser.isEdgeLegacy ? 'mousewheel' : 'wheel',
MOUSE_WHEEL: 'wheel',
POINTER_UP: 'pointerup',
POINTER_DOWN: 'pointerdown',
POINTER_MOVE: 'pointermove',
@@ -1230,6 +1230,10 @@ export function asCSSUrl(uri: URI): string {
return `url('${FileAccess.asBrowserUri(uri).toString(true).replace(/'/g, '%27')}')`;
}
export function asCSSPropertyValue(value: string) {
return `'${value.replace(/'/g, '%27')}'`;
}
export function triggerDownload(dataOrUri: Uint8Array | URI, name: string): void {
// If the data is provided as Buffer, we create a
@@ -1471,7 +1475,7 @@ export class ModifierKeyEmitter extends Emitter<IModifierKeyStatus> {
metaKey: false
};
this._subscriptions.add(domEvent(document.body, 'keydown', true)(e => {
this._subscriptions.add(domEvent(window, 'keydown', true)(e => {
const event = new StandardKeyboardEvent(e);
// If Alt-key keydown event is repeated, ignore it #112347
@@ -1505,7 +1509,7 @@ export class ModifierKeyEmitter extends Emitter<IModifierKeyStatus> {
}
}));
this._subscriptions.add(domEvent(document.body, 'keyup', true)(e => {
this._subscriptions.add(domEvent(window, 'keyup', true)(e => {
if (!e.altKey && this._keyStatus.altKey) {
this._keyStatus.lastKeyReleased = 'alt';
} else if (!e.ctrlKey && this._keyStatus.ctrlKey) {

View File

@@ -31,10 +31,12 @@ export interface CancellableEvent {
stopPropagation(): void;
}
export function stopEvent<T extends CancellableEvent>(event: T): T {
event.preventDefault();
event.stopPropagation();
return event;
}
export function stop<T extends CancellableEvent>(event: BaseEvent<T>): BaseEvent<T> {
return BaseEvent.map(event, e => {
e.preventDefault();
e.stopPropagation();
return e;
});
}
return BaseEvent.map(event, stopEvent);
}

View File

@@ -383,5 +383,16 @@ export function renderMarkdownAsPlaintext(markdown: IMarkdownString) {
if (value.length > 100_000) {
value = `${value.substr(0, 100_000)}`;
}
return sanitizeRenderedMarkdown({ isTrusted: false }, marked.parse(value, { renderer })).toString();
const unescapeInfo = new Map<string, string>([
['&quot;', '"'],
['&amp;', '&'],
['&#39;', '\''],
['&lt;', '<'],
['&gt;', '>'],
]);
const html = marked.parse(value, { renderer }).replace(/&(#\d+|[a-zA-Z]+);/g, m => unescapeInfo.get(m) ?? m);
return sanitizeRenderedMarkdown({ isTrusted: false }, html).toString();
}

View File

@@ -8,13 +8,14 @@ import * as platform from 'vs/base/common/platform';
import * as nls from 'vs/nls';
import { Disposable } from 'vs/base/common/lifecycle';
import { SelectBox, ISelectOptionItem, ISelectBoxOptions } from 'vs/base/browser/ui/selectBox/selectBox';
import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner, Separator, IActionViewItem } from 'vs/base/common/actions';
import { IAction, IActionRunner, Action, IActionChangeEvent, ActionRunner, Separator } from 'vs/base/common/actions';
import * as types from 'vs/base/common/types';
import { EventType as TouchEventType, Gesture } from 'vs/base/browser/touch';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { DataTransfers } from 'vs/base/browser/dnd';
import { isFirefox } from 'vs/base/browser/browser';
import { $, addDisposableListener, append, EventHelper, EventLike, EventType, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom';
import { $, addDisposableListener, append, EventHelper, EventLike, EventType } from 'vs/base/browser/dom';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
export interface IBaseActionViewItemOptions {
draggable?: boolean;
@@ -163,8 +164,11 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
this.actionRunner.run(this._action, context);
}
// Only set the tabIndex on the element once it is about to get focused
// That way this element wont be a tab stop when it is not needed #106441
focus(): void {
if (this.element) {
this.element.tabIndex = 0;
this.element.focus();
this.element.classList.add('focused');
}
@@ -173,10 +177,21 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
blur(): void {
if (this.element) {
this.element.blur();
this.element.tabIndex = -1;
this.element.classList.remove('focused');
}
}
setFocusable(focusable: boolean): void {
if (this.element) {
this.element.tabIndex = focusable ? 0 : -1;
}
}
get trapsArrowNavigation(): boolean {
return false;
}
protected updateEnabled(): void {
// implement in subclass
}
@@ -259,14 +274,27 @@ export class ActionViewItem extends BaseActionViewItem {
this.updateChecked();
}
// Only set the tabIndex on the element once it is about to get focused
// That way this element wont be a tab stop when it is not needed #106441
focus(): void {
super.focus();
if (this.label) {
this.label.tabIndex = 0;
this.label.focus();
}
}
blur(): void {
if (this.label) {
this.label.tabIndex = -1;
}
}
setFocusable(focusable: boolean): void {
if (this.label) {
this.label.tabIndex = focusable ? 0 : -1;
}
}
updateLabel(): void {
if (this.options.label && this.label) {
this.label.textContent = this.getAction().label;
@@ -320,7 +348,6 @@ export class ActionViewItem extends BaseActionViewItem {
if (this.label) {
this.label.removeAttribute('aria-disabled');
this.label.classList.remove('disabled');
this.label.tabIndex = 0;
}
if (this.element) {
@@ -330,7 +357,6 @@ export class ActionViewItem extends BaseActionViewItem {
if (this.label) {
this.label.setAttribute('aria-disabled', 'true');
this.label.classList.add('disabled');
removeTabIndexAndUpdateFocus(this.label);
}
if (this.element) {

View File

@@ -55,6 +55,7 @@
}
.monaco-action-bar .action-item.disabled .action-label,
.monaco-action-bar .action-item.disabled .action-label::before,
.monaco-action-bar .action-item.disabled .action-label:hover {
opacity: 0.4;
}

View File

@@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./actionbar';
import { Disposable, dispose } from 'vs/base/common/lifecycle';
import { IAction, IActionRunner, ActionRunner, IRunEvent, Separator, IActionViewItem, IActionViewItemProvider } from 'vs/base/common/actions';
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IAction, IActionRunner, ActionRunner, IRunEvent, Separator } from 'vs/base/common/actions';
import * as DOM from 'vs/base/browser/dom';
import * as types from 'vs/base/common/types';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -13,6 +13,19 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Emitter } from 'vs/base/common/event';
import { IActionViewItemOptions, ActionViewItem, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
export interface IActionViewItem extends IDisposable {
actionRunner: IActionRunner;
setActionContext(context: any): void;
render(element: HTMLElement): void;
isEnabled(): boolean;
focus(fromRight?: boolean): void; // TODO@isidorn what is this?
blur(): void;
}
export interface IActionViewItemProvider {
(action: IAction): IActionViewItem | undefined;
}
export const enum ActionsOrientation {
HORIZONTAL,
HORIZONTAL_REVERSE,
@@ -35,7 +48,7 @@ export interface IActionBarOptions {
readonly triggerKeys?: ActionTrigger;
readonly allowContextMenu?: boolean;
readonly preventLoopNavigation?: boolean;
readonly ignoreOrientationForPreviousAndNextKey?: boolean;
readonly focusOnlyEnabledItems?: boolean;
}
export interface IActionOptions extends IActionViewItemOptions {
@@ -63,6 +76,8 @@ export class ActionBar extends Disposable implements IActionRunner {
// Trigger Key Tracking
private triggerKeyDown: boolean = false;
private focusable: boolean = true;
// Elements
domNode: HTMLElement;
protected actionsList: HTMLElement;
@@ -117,22 +132,22 @@ export class ActionBar extends Disposable implements IActionRunner {
switch (this._orientation) {
case ActionsOrientation.HORIZONTAL:
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.LeftArrow];
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.RightArrow];
previousKeys = [KeyCode.LeftArrow];
nextKeys = [KeyCode.RightArrow];
break;
case ActionsOrientation.HORIZONTAL_REVERSE:
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.RightArrow];
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.LeftArrow];
previousKeys = [KeyCode.RightArrow];
nextKeys = [KeyCode.LeftArrow];
this.domNode.className += ' reverse';
break;
case ActionsOrientation.VERTICAL:
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.UpArrow];
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.DownArrow];
previousKeys = [KeyCode.UpArrow];
nextKeys = [KeyCode.DownArrow];
this.domNode.className += ' vertical';
break;
case ActionsOrientation.VERTICAL_REVERSE:
previousKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.RightArrow, KeyCode.DownArrow] : [KeyCode.DownArrow];
nextKeys = this.options.ignoreOrientationForPreviousAndNextKey ? [KeyCode.LeftArrow, KeyCode.UpArrow] : [KeyCode.UpArrow];
previousKeys = [KeyCode.DownArrow];
nextKeys = [KeyCode.UpArrow];
this.domNode.className += ' vertical reverse';
break;
}
@@ -140,6 +155,7 @@ export class ActionBar extends Disposable implements IActionRunner {
this._register(DOM.addDisposableListener(this.domNode, DOM.EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
let eventHandled = true;
const focusedItem = typeof this.focusedItem === 'number' ? this.viewItems[this.focusedItem] : undefined;
if (previousKeys && (event.equals(previousKeys[0]) || event.equals(previousKeys[1]))) {
eventHandled = this.focusPrevious();
@@ -147,6 +163,8 @@ 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.Tab) && focusedItem instanceof BaseActionViewItem && focusedItem.trapsArrowNavigation) {
this.focusNext();
} else if (this.isTriggerKeyEvent(event)) {
// Staying out of the else branch even if not triggered
if (this._triggerKeys.keyDown) {
@@ -216,6 +234,25 @@ export class ActionBar extends Disposable implements IActionRunner {
}
}
// Some action bars should not be focusable at times
// When an action bar is not focusable make sure to make all the elements inside it not focusable
// When an action bar is focusable again, make sure the first item can be focused
setFocusable(focusable: boolean): void {
this.focusable = focusable;
if (this.focusable) {
const firstEnabled = this.viewItems.find(vi => vi instanceof BaseActionViewItem && vi.isEnabled());
if (firstEnabled instanceof BaseActionViewItem) {
firstEnabled.setFocusable(true);
}
} else {
this.viewItems.forEach(vi => {
if (vi instanceof BaseActionViewItem) {
vi.setFocusable(false);
}
});
}
}
private isTriggerKeyEvent(event: StandardKeyboardEvent): boolean {
let ret = false;
this._triggerKeys.keys.forEach(keyCode => {
@@ -294,6 +331,11 @@ export class ActionBar extends Disposable implements IActionRunner {
item.setActionContext(this.context);
item.render(actionViewItemElement);
if (this.focusable && item instanceof BaseActionViewItem && this.viewItems.length === 0) {
// We need to allow for the first enabled item to be focused on using tab navigation #106441
item.setFocusable(true);
}
if (index === null || index < 0 || index >= this.actionsList.children.length) {
this.actionsList.appendChild(actionViewItemElement);
this.viewItems.push(item);
@@ -305,7 +347,7 @@ export class ActionBar extends Disposable implements IActionRunner {
index++;
}
});
if (this.focusedItem) {
if (typeof this.focusedItem === 'number') {
// After a clear actions might be re-added to simply toggle some actions. We should preserve focus #97128
this.focus(this.focusedItem);
}
@@ -390,8 +432,8 @@ export class ActionBar extends Disposable implements IActionRunner {
const startIndex = this.focusedItem;
let item: IActionViewItem;
do {
if (this.options.preventLoopNavigation && this.focusedItem + 1 >= this.viewItems.length) {
this.focusedItem = startIndex;
return false;
@@ -399,11 +441,7 @@ export class ActionBar extends Disposable implements IActionRunner {
this.focusedItem = (this.focusedItem + 1) % this.viewItems.length;
item = this.viewItems[this.focusedItem];
} while (this.focusedItem !== startIndex && !item.isEnabled());
if (this.focusedItem === startIndex && !item.isEnabled()) {
this.focusedItem = undefined;
}
} while (this.focusedItem !== startIndex && this.options.focusOnlyEnabledItems && !item.isEnabled());
this.updateFocus();
return true;
@@ -419,7 +457,6 @@ export class ActionBar extends Disposable implements IActionRunner {
do {
this.focusedItem = this.focusedItem - 1;
if (this.focusedItem < 0) {
if (this.options.preventLoopNavigation) {
this.focusedItem = startIndex;
@@ -428,13 +465,9 @@ export class ActionBar extends Disposable implements IActionRunner {
this.focusedItem = this.viewItems.length - 1;
}
item = this.viewItems[this.focusedItem];
} while (this.focusedItem !== startIndex && !item.isEnabled());
} while (this.focusedItem !== startIndex && this.options.focusOnlyEnabledItems && !item.isEnabled());
if (this.focusedItem === startIndex && !item.isEnabled()) {
this.focusedItem = undefined;
}
this.updateFocus(true);
return true;
@@ -450,12 +483,20 @@ export class ActionBar extends Disposable implements IActionRunner {
const actionViewItem = item;
if (i === this.focusedItem) {
if (types.isFunction(actionViewItem.isEnabled)) {
if (actionViewItem.isEnabled() && types.isFunction(actionViewItem.focus)) {
actionViewItem.focus(fromRight);
} else {
this.actionsList.focus({ preventScroll });
}
let focusItem = true;
if (!types.isFunction(actionViewItem.focus)) {
focusItem = false;
}
if (this.options.focusOnlyEnabledItems && types.isFunction(item.isEnabled) && !item.isEnabled()) {
focusItem = false;
}
if (focusItem) {
actionViewItem.focus(fromRight);
} else {
this.actionsList.focus({ preventScroll });
}
} else {
if (types.isFunction(actionViewItem.blur)) {

View File

@@ -12,7 +12,7 @@ import { Event as BaseEvent, Emitter } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch';
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset, removeTabIndexAndUpdateFocus } from 'vs/base/browser/dom';
import { addDisposableListener, IFocusTracker, EventType, EventHelper, trackFocus, reset } from 'vs/base/browser/dom';
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
import { CSSIcon, Codicon } from 'vs/base/common/codicons';
@@ -214,7 +214,6 @@ export class Button extends Disposable implements IButton {
} else {
this._element.classList.add('disabled');
this._element.setAttribute('aria-disabled', String(true));
removeTabIndexAndUpdateFocus(this._element);
}
}

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./checkbox';
import * as DOM from 'vs/base/browser/dom';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Widget } from 'vs/base/browser/ui/widget';
import { Color } from 'vs/base/common/color';
@@ -19,6 +18,7 @@ export interface ICheckboxOpts extends ICheckboxStyles {
readonly icon?: CSSIcon;
readonly title: string;
readonly isChecked: boolean;
readonly notFocusable?: boolean;
}
export interface ICheckboxStyles {
@@ -51,7 +51,8 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
this.checkbox = new Checkbox({
actionClassName: this._action.class,
isChecked: this._action.checked,
title: this._action.label
title: this._action.label,
notFocusable: true
});
this.disposables.add(this.checkbox);
this.disposables.add(this.checkbox.onChange(() => this._action.checked = !!this.checkbox && this.checkbox.checked, this));
@@ -74,6 +75,26 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
}
}
focus(): void {
if (this.checkbox) {
this.checkbox.domNode.tabIndex = 0;
this.checkbox.focus();
}
}
blur(): void {
if (this.checkbox) {
this.checkbox.domNode.tabIndex = -1;
this.checkbox.domNode.blur();
}
}
setFocusable(focusable: boolean): void {
if (this.checkbox) {
this.checkbox.domNode.tabIndex = focusable ? 0 : -1;
}
}
dispose(): void {
this.disposables.dispose();
super.dispose();
@@ -113,7 +134,9 @@ export class Checkbox extends Widget {
this.domNode = document.createElement('div');
this.domNode.title = this._opts.title;
this.domNode.classList.add(...classes);
this.domNode.tabIndex = 0;
if (!this._opts.notFocusable) {
this.domNode.tabIndex = 0;
}
this.domNode.setAttribute('role', 'checkbox');
this.domNode.setAttribute('aria-checked', String(this._checked));
this.domNode.setAttribute('aria-label', this._opts.title);
@@ -187,12 +210,10 @@ export class Checkbox extends Widget {
}
enable(): void {
this.domNode.tabIndex = 0;
this.domNode.setAttribute('aria-disabled', String(false));
}
disable(): void {
DOM.removeTabIndexAndUpdateFocus(this.domNode);
this.domNode.setAttribute('aria-disabled', String(true));
}
}

View File

@@ -13,7 +13,7 @@
}
}
.codicon-sync.codicon-modifier-spin, .codicon-loading.codicon-modifier-spin{
.codicon-sync.codicon-modifier-spin, .codicon-loading.codicon-modifier-spin, .codicon-gear.codicon-modifier-spin {
/* Use steps to throttle FPS to reduce CPU usage */
animation: codicon-spin 1.5s steps(30) infinite;
}

View File

@@ -13,5 +13,5 @@ export function formatRule(c: Codicon) {
while (def instanceof Codicon) {
def = def.definition;
}
return `.codicon-${c.id}:before { content: '${def.character}'; }`;
return `.codicon-${c.id}:before { content: '${def.fontCharacter}'; }`;
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./dropdown';
import { Action, IAction, IActionRunner, IActionViewItemProvider } from 'vs/base/common/actions';
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
import { IDisposable } from 'vs/base/common/lifecycle';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
@@ -14,6 +14,7 @@ import { ActionViewItem, BaseActionViewItem, IActionViewItemOptions, IBaseAction
import { IActionProvider, DropdownMenu, IDropdownMenuOptions, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { Codicon } from 'vs/base/common/codicons';
import { IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
export interface IKeybindingProvider {
(action: IAction): ResolvedKeybinding | undefined;
@@ -78,7 +79,6 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
this.element.classList.add(...classNames);
this.element.tabIndex = 0;
this.element.setAttribute('role', 'button');
this.element.setAttribute('aria-haspopup', 'true');
this.element.setAttribute('aria-expanded', 'false');
@@ -173,12 +173,14 @@ export class ActionWithDropdownActionViewItem extends ActionViewItem {
const menuActionsProvider = {
getActions: () => {
const actionsProvider = (<IActionWithDropdownActionViewItemOptions>this.options).menuActionsOrProvider;
return [this._action, ...(Array.isArray(actionsProvider) ? actionsProvider : actionsProvider.getActions())];
return [this._action, ...(Array.isArray(actionsProvider)
? actionsProvider
: (actionsProvider as IActionProvider).getActions()) // TODO: microsoft/TypeScript#42768
];
}
};
this.dropdownMenuActionViewItem = new DropdownMenuActionViewItem(this._register(new Action('dropdownAction', undefined)), menuActionsProvider, this.contextMenuProvider, { classNames: ['dropdown', ...Codicon.dropDownButton.classNamesArray, ...(<IActionWithDropdownActionViewItemOptions>this.options).menuActionClassNames || []] });
this.dropdownMenuActionViewItem.render(this.element);
}
}
}

View File

@@ -20,5 +20,4 @@ export interface IHoverDelegateOptions {
export interface IHoverDelegate {
showHover(options: IHoverDelegateOptions): IDisposable | undefined;
hideHover(): void;
}

View File

@@ -192,13 +192,14 @@ export class IconLabel extends Disposable {
}
}
private static adjustXAndShowCustomHover(hoverOptions: IHoverDelegateOptions | undefined, mouseX: number | undefined, hoverDelegate: IHoverDelegate, isHovering: boolean) {
private static adjustXAndShowCustomHover(hoverOptions: IHoverDelegateOptions | undefined, mouseX: number | undefined, hoverDelegate: IHoverDelegate, isHovering: boolean): IDisposable | undefined {
if (hoverOptions && isHovering) {
if (mouseX !== undefined) {
(<IHoverDelegateTarget>hoverOptions.target).x = mouseX + 10;
}
hoverDelegate.showHover(hoverOptions);
return hoverDelegate.showHover(hoverOptions);
}
return undefined;
}
private getTooltipForCustom(markdownTooltip: string | IIconLabelMarkdownString): (token: CancellationToken) => Promise<string | IMarkdownString | undefined> {
@@ -224,17 +225,22 @@ export class IconLabel extends Disposable {
let mouseX: number | undefined;
let isHovering = false;
let tokenSource: CancellationTokenSource;
let hoverDisposable: IDisposable | undefined;
function mouseOver(this: HTMLElement, e: MouseEvent): any {
if (isHovering) {
return;
}
tokenSource = new CancellationTokenSource();
function mouseLeaveOrDown(this: HTMLElement, e: MouseEvent): any {
isHovering = false;
hoverOptions = undefined;
tokenSource.dispose(true);
mouseLeaveDisposable.dispose();
mouseDownDisposable.dispose();
if ((e.type === dom.EventType.MOUSE_DOWN) || (<any>e).fromElement === htmlElement) {
hoverDisposable?.dispose();
hoverDisposable = undefined;
isHovering = false;
hoverOptions = undefined;
tokenSource.dispose(true);
mouseLeaveDisposable.dispose();
mouseDownDisposable.dispose();
}
}
const mouseLeaveDisposable = domEvent(htmlElement, dom.EventType.MOUSE_LEAVE, true)(mouseLeaveOrDown.bind(htmlElement));
const mouseDownDisposable = domEvent(htmlElement, dom.EventType.MOUSE_DOWN, true)(mouseLeaveOrDown.bind(htmlElement));
@@ -257,7 +263,7 @@ export class IconLabel extends Disposable {
target,
anchorPosition: AnchorPosition.BELOW
};
IconLabel.adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);
hoverDisposable = IconLabel.adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);
const resolvedTooltip = (await tooltip(tokenSource.token)) ?? (!isString(markdownTooltip) ? markdownTooltip.markdownNotSupportedFallback : undefined);
if (resolvedTooltip) {
@@ -267,11 +273,13 @@ export class IconLabel extends Disposable {
anchorPosition: AnchorPosition.BELOW
};
// awaiting the tooltip could take a while. Make sure we're still hovering.
IconLabel.adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);
} else {
hoverDelegate.hideHover();
hoverDisposable = IconLabel.adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);
} else if (hoverDisposable) {
hoverDisposable.dispose();
hoverDisposable = undefined;
}
}
}
mouseMoveDisposable.dispose();
}, hoverDelay);

View File

@@ -6,8 +6,7 @@
import * as dom from 'vs/base/browser/dom';
import { CSSIcon } from 'vs/base/common/codicons';
const labelWithIconsRegex = /(\\)?\$\(([a-z\-]+(?:~[a-z\-]+)?)\)/gi;
const labelWithIconsRegex = new RegExp(`(\\\\)?\\$\\((${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?)\\)`, 'g');
export function renderLabelWithIcons(text: string): Array<HTMLSpanElement | string> {
const elements = new Array<HTMLSpanElement | string>();
let match: RegExpMatchArray | null;

View File

@@ -89,7 +89,6 @@
padding: 0.4em;
font-size: 12px;
line-height: 17px;
min-height: 34px;
margin-top: -1px;
word-wrap: break-word;
}

View File

@@ -292,6 +292,9 @@ export class InputBox extends Widget {
if (range) {
this.input.setSelectionRange(range.start, range.end);
if (range.end === this.input.value.length) {
this.input.scrollLeft = this.input.scrollWidth;
}
}
}

View File

@@ -15,7 +15,7 @@ export interface IListVirtualDelegate<T> {
}
export interface IListRenderer<T, TTemplateData> {
templateId: string;
readonly templateId: string;
renderTemplate(container: HTMLElement): TTemplateData;
renderElement(element: T, index: number, templateData: TTemplateData, height: number | undefined): void;
disposeElement?(element: T, index: number, templateData: TTemplateData, height: number | undefined): void;

View File

@@ -64,6 +64,7 @@ export interface IListViewOptions<T> extends IListViewOptionsUpdate {
readonly mouseSupport?: boolean;
readonly accessibilityProvider?: IListViewAccessibilityProvider<T>;
readonly transformOptimization?: boolean;
readonly alwaysConsumeMouseWheel?: boolean;
}
const DefaultOptions = {
@@ -80,7 +81,8 @@ const DefaultOptions = {
drop() { }
},
horizontalScrolling: false,
transformOptimization: true
transformOptimization: true,
alwaysConsumeMouseWheel: true,
};
export class ElementsDragAndDropData<T, TContext = void> implements IDragAndDropData {
@@ -327,6 +329,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.scrollable = new Scrollable(getOrDefault(options, o => o.smoothScrolling, false) ? 125 : 0, cb => scheduleAtNextAnimationFrame(cb));
this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
alwaysConsumeMouseWheel: getOrDefault(options, o => o.alwaysConsumeMouseWheel, DefaultOptions.alwaysConsumeMouseWheel),
horizontal: ScrollbarVisibility.Auto,
vertical: getOrDefault(options, o => o.verticalScrollMode, DefaultOptions.verticalScrollMode),
useShadows: getOrDefault(options, o => o.useShadows, DefaultOptions.useShadows),
@@ -433,7 +436,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
const removeRange = Range.intersect(previousRenderRange, deleteRange);
// try to reuse rows, avoid removing them from DOM
const rowsToDispose = new Map<string, [IRow, T, number, number][]>();
const rowsToDispose = new Map<string, IRow[]>();
for (let i = removeRange.start; i < removeRange.end; i++) {
const item = this.items[i];
item.dragStartDisposable.dispose();
@@ -446,7 +449,13 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
rowsToDispose.set(item.templateId, rows);
}
rows.push([item.row, item.element, i, item.size]);
const renderer = this.renderers.get(item.templateId);
if (renderer && renderer.disposeElement) {
renderer.disposeElement(item.element, i, item.row.templateData, item.size);
}
rows.push(item.row);
}
item.row = null;
@@ -476,8 +485,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if (start === 0 && deleteCount >= this.items.length) {
this.rangeMap = new RangeMap();
this.rangeMap.splice(0, 0, inserted);
deleted = this.items;
this.items = inserted;
deleted = [];
} else {
this.rangeMap.splice(start, deleteCount, inserted);
deleted = this.items.splice(start, deleteCount, ...inserted);
@@ -509,31 +518,13 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
for (let i = range.start; i < range.end; i++) {
const item = this.items[i];
const rows = rowsToDispose.get(item.templateId);
const rowData = rows?.pop();
if (!rowData) {
this.insertItemInDOM(i, beforeElement);
} else {
const [row, element, index, size] = rowData;
const renderer = this.renderers.get(item.templateId);
if (renderer && renderer.disposeElement) {
renderer.disposeElement(element, index, row.templateData, size);
}
this.insertItemInDOM(i, beforeElement, row);
}
const row = rows?.pop();
this.insertItemInDOM(i, beforeElement, row);
}
}
for (const [templateId, rows] of rowsToDispose) {
for (const [row, element, index, size] of rows) {
const renderer = this.renderers.get(templateId);
if (renderer && renderer.disposeElement) {
renderer.disposeElement(element, index, row.templateData, size);
}
for (const rows of rowsToDispose.values()) {
for (const row of rows) {
this.cache.release(row);
}
}

View File

@@ -13,7 +13,7 @@ import { Gesture } from 'vs/base/browser/touch';
import { KeyCode } from 'vs/base/common/keyCodes';
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Event, Emitter, EventBufferer } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { domEvent, stopEvent } from 'vs/base/browser/event';
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListError, IKeyboardNavigationDelegate } from './list';
import { ListView, IListViewOptions, IListViewDragAndDrop, IListViewAccessibilityProvider, IListViewOptionsUpdate } from './listView';
import { Color } from 'vs/base/common/color';
@@ -761,6 +761,11 @@ export class DefaultStyleController implements IStyleController {
`);
}
if (styles.listInactiveFocusForeground) {
content.push(`.monaco-list${suffix} .monaco-list-row.focused { color: ${styles.listInactiveFocusForeground}; }`);
content.push(`.monaco-list${suffix} .monaco-list-row.focused:hover { color: ${styles.listInactiveFocusForeground}; }`); // overwrite :hover style in this case!
}
if (styles.listInactiveFocusBackground) {
content.push(`.monaco-list${suffix} .monaco-list-row.focused { background-color: ${styles.listInactiveFocusBackground}; }`);
content.push(`.monaco-list${suffix} .monaco-list-row.focused:hover { background-color: ${styles.listInactiveFocusBackground}; }`); // overwrite :hover style in this case!
@@ -776,7 +781,7 @@ export class DefaultStyleController implements IStyleController {
}
if (styles.listHoverBackground) {
content.push(`.monaco-list${suffix}:not(.drop-target) .monaco-list-row:hover:not(.selected):not(.focused) { background-color: ${styles.listHoverBackground}; }`);
content.push(`.monaco-list${suffix}:not(.drop-target) .monaco-list-row:hover:not(.selected):not(.focused) { background-color: ${styles.listHoverBackground}; }`);
}
if (styles.listHoverForeground) {
@@ -826,6 +831,14 @@ export class DefaultStyleController implements IStyleController {
content.push(`.monaco-list-type-filter { box-shadow: 1px 1px 1px ${styles.listMatchesShadow}; }`);
}
if (styles.tableColumnsBorder) {
content.push(`
.monaco-table:hover > .monaco-split-view2,
.monaco-table:hover > .monaco-split-view2 .monaco-sash.vertical::before {
border-color: ${styles.tableColumnsBorder};
}`);
}
this.styleElement.textContent = content.join('\n');
}
}
@@ -854,6 +867,7 @@ export interface IListOptions<T> {
readonly additionalScrollHeight?: number;
readonly transformOptimization?: boolean;
readonly smoothScrolling?: boolean;
readonly alwaysConsumeMouseWheel?: boolean;
}
export interface IListStyles {
@@ -866,6 +880,7 @@ export interface IListStyles {
listFocusAndSelectionForeground?: Color;
listInactiveSelectionBackground?: Color;
listInactiveSelectionForeground?: Color;
listInactiveFocusForeground?: Color;
listInactiveFocusBackground?: Color;
listHoverBackground?: Color;
listHoverForeground?: Color;
@@ -879,6 +894,7 @@ export interface IListStyles {
listFilterWidgetNoMatchesOutline?: Color;
listMatchesShadow?: Color;
treeIndentGuidesStroke?: Color;
tableColumnsBorder?: Color;
}
const defaultStyles: IListStyles = {
@@ -890,7 +906,8 @@ const defaultStyles: IListStyles = {
listInactiveSelectionBackground: Color.fromHex('#3F3F46'),
listHoverBackground: Color.fromHex('#2A2D2E'),
listDropBackground: Color.fromHex('#383B3D'),
treeIndentGuidesStroke: Color.fromHex('#a9a9a9')
treeIndentGuidesStroke: Color.fromHex('#a9a9a9'),
tableColumnsBorder: Color.fromHex('#cccccc').transparent(0.2)
};
const DefaultOptions: IListOptions<any> = {
@@ -1148,35 +1165,43 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
get onTouchStart(): Event<IListTouchEvent<T>> { return this.view.onTouchStart; }
get onTap(): Event<IListGestureEvent<T>> { return this.view.onTap; }
private didJustPressContextMenuKey: boolean = false;
/**
* Possible context menu trigger events:
* - ContextMenu key
* - Shift F10
* - Ctrl Option Shift M (macOS with VoiceOver)
* - Mouse right click
*/
@memoize get onContextMenu(): Event<IListContextMenuEvent<T>> {
const fromKeydown = Event.chain(domEvent(this.view.domNode, 'keydown'))
let didJustPressContextMenuKey = false;
const fromKeyDown = Event.chain(domEvent(this.view.domNode, 'keydown'))
.map(e => new StandardKeyboardEvent(e))
.filter(e => this.didJustPressContextMenuKey = e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10))
.filter(e => { e.preventDefault(); e.stopPropagation(); return false; })
.filter(e => didJustPressContextMenuKey = e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10))
.map(stopEvent)
.filter(() => false)
.event as Event<any>;
const fromKeyup = Event.chain(domEvent(this.view.domNode, 'keyup'))
.filter(() => {
const didJustPressContextMenuKey = this.didJustPressContextMenuKey;
this.didJustPressContextMenuKey = false;
return didJustPressContextMenuKey;
})
.filter(() => this.getFocus().length > 0 && !!this.view.domElement(this.getFocus()[0]))
.map(browserEvent => {
const index = this.getFocus()[0];
const element = this.view.element(index);
const anchor = this.view.domElement(index) as HTMLElement;
const fromKeyUp = Event.chain(domEvent(this.view.domNode, 'keyup'))
.forEach(() => didJustPressContextMenuKey = false)
.map(e => new StandardKeyboardEvent(e))
.filter(e => e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10))
.map(stopEvent)
.map(({ browserEvent }) => {
const focus = this.getFocus();
const index = focus.length ? focus[0] : undefined;
const element = typeof index !== 'undefined' ? this.view.element(index) : undefined;
const anchor = typeof index !== 'undefined' ? this.view.domElement(index) as HTMLElement : this.view.domNode;
return { index, element, anchor, browserEvent };
})
.event;
const fromMouse = Event.chain(this.view.onContextMenu)
.filter(() => !this.didJustPressContextMenuKey)
.filter(_ => !didJustPressContextMenuKey)
.map(({ element, index, browserEvent }) => ({ element, index, anchor: { x: browserEvent.clientX + 1, y: browserEvent.clientY }, browserEvent }))
.event;
return Event.any<IListContextMenuEvent<T>>(fromKeydown, fromKeyup, fromMouse);
return Event.any<IListContextMenuEvent<T>>(fromKeyDown, fromKeyUp, fromMouse);
}
get onKeyDown(): Event<KeyboardEvent> { return domEvent(this.view.domNode, 'keydown'); }
@@ -1380,7 +1405,7 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
}
domFocus(): void {
this.view.domNode.focus();
this.view.domNode.focus({ preventScroll: true });
}
layout(height?: number, width?: number): void {

View File

@@ -5,10 +5,10 @@
import * as nls from 'vs/nls';
import * as strings from 'vs/base/common/strings';
import { IActionRunner, IAction, SubmenuAction, Separator, IActionViewItemProvider, EmptySubmenuAction } from 'vs/base/common/actions';
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { IActionRunner, IAction, SubmenuAction, Separator, EmptySubmenuAction } from 'vs/base/common/actions';
import { ActionBar, ActionsOrientation, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
import { EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, addDisposableListener, append, $, clearNode, createStyleSheet, isInShadowDOM, getActiveElement, Dimension, IDomNodePagePosition } from 'vs/base/browser/dom';
import { EventType, EventHelper, EventLike, isAncestor, addDisposableListener, append, $, clearNode, createStyleSheet, isInShadowDOM, getActiveElement, Dimension, IDomNodePagePosition } from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { RunOnceScheduler } from 'vs/base/common/async';
import { DisposableStore } from 'vs/base/common/lifecycle';
@@ -86,6 +86,7 @@ export class Menu extends ActionBar {
context: options.context,
actionRunner: options.actionRunner,
ariaLabel: options.ariaLabel,
focusOnlyEnabledItems: true,
triggerKeys: { keys: [KeyCode.Enter, ...(isMacintosh || isLinux ? [KeyCode.Space] : [])], keyDown: true }
});
@@ -617,20 +618,23 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
if (this.getAction().enabled) {
if (this.element) {
this.element.classList.remove('disabled');
this.element.removeAttribute('aria-disabled');
}
if (this.item) {
this.item.classList.remove('disabled');
this.item.removeAttribute('aria-disabled');
this.item.tabIndex = 0;
}
} else {
if (this.element) {
this.element.classList.add('disabled');
this.element.setAttribute('aria-disabled', 'true');
}
if (this.item) {
this.item.classList.add('disabled');
removeTabIndexAndUpdateFocus(this.item);
this.item.setAttribute('aria-disabled', 'true');
}
}
}

View File

@@ -42,7 +42,7 @@
}
.menubar .menubar-menu-items-holder {
position: absolute;
position: fixed;
left: 0px;
opacity: 1;
z-index: 2000;

View File

@@ -746,7 +746,7 @@ export class MenuBar extends Disposable {
private setUnfocusedState(): void {
if (this.options.visibility === 'toggle' || this.options.visibility === 'hidden') {
this.focusState = MenubarState.HIDDEN;
} else if (this.options.visibility === 'default' && browser.isFullscreen()) {
} else if (this.options.visibility === 'classic' && browser.isFullscreen()) {
this.focusState = MenubarState.HIDDEN;
} else {
this.focusState = MenubarState.VISIBLE;
@@ -838,6 +838,22 @@ export class MenuBar extends Disposable {
this._mnemonicsInUse = value;
}
private get shouldAltKeyFocus(): boolean {
if (isMacintosh) {
return false;
}
if (!this.options.disableAltFocus) {
return true;
}
if (this.options.visibility === 'toggle') {
return true;
}
return false;
}
public get onVisibilityChange(): Event<boolean> {
return this._onVisibilityChange.event;
}
@@ -869,7 +885,7 @@ export class MenuBar extends Disposable {
}
// Prevent alt-key default if the menu is not hidden and we use alt to focus
if (modifierKeyStatus.event && !this.options.disableAltFocus) {
if (modifierKeyStatus.event && this.shouldAltKeyFocus) {
if (ScanCodeUtils.toEnum(modifierKeyStatus.event.code) === ScanCode.AltLeft) {
modifierKeyStatus.event.preventDefault();
}
@@ -885,7 +901,7 @@ export class MenuBar extends Disposable {
// Clean alt key press and release
if (allModifiersReleased && modifierKeyStatus.lastKeyPressed === 'alt' && modifierKeyStatus.lastKeyReleased === 'alt') {
if (!this.awaitingAltRelease) {
if (!this.isFocused && !(this.options.disableAltFocus && this.options.visibility !== 'toggle')) {
if (!this.isFocused && this.shouldAltKeyFocus) {
this.mnemonicsInUse = true;
this.focusedMenu = { index: this.numMenusShown > 0 ? 0 : MenuBar.OVERFLOW_INDEX };
this.focusState = MenubarState.FOCUSED;

View File

@@ -60,8 +60,7 @@
height: var(--sash-size);
}
.monaco-sash:not(.disabled).orthogonal-start::before,
.monaco-sash:not(.disabled).orthogonal-end::after {
.monaco-sash:not(.disabled) > .orthogonal-drag-handle {
content: " ";
height: calc(var(--sash-size) * 2);
width: calc(var(--sash-size) * 2);
@@ -71,30 +70,34 @@
position: absolute;
}
.monaco-sash.horizontal.orthogonal-edge-north:not(.disabled).orthogonal-start::before,
.monaco-sash.horizontal.orthogonal-edge-south:not(.disabled).orthogonal-end::after {
.monaco-sash.horizontal.orthogonal-edge-north:not(.disabled)
> .orthogonal-drag-handle.start,
.monaco-sash.horizontal.orthogonal-edge-south:not(.disabled)
> .orthogonal-drag-handle.end {
cursor: nwse-resize;
}
.monaco-sash.horizontal.orthogonal-edge-north:not(.disabled).orthogonal-end::after,
.monaco-sash.horizontal.orthogonal-edge-south:not(.disabled).orthogonal-start::before {
.monaco-sash.horizontal.orthogonal-edge-north:not(.disabled)
> .orthogonal-drag-handle.end,
.monaco-sash.horizontal.orthogonal-edge-south:not(.disabled)
> .orthogonal-drag-handle.start {
cursor: nesw-resize;
}
.monaco-sash.orthogonal-start.vertical::before {
left: -calc(var(--sash-size) / 2);
.monaco-sash.vertical > .orthogonal-drag-handle.start {
left: calc(var(--sash-size) / -2);
top: calc(var(--sash-size) * -1);
}
.monaco-sash.orthogonal-end.vertical::after {
left: -calc(var(--sash-size) / 2);
.monaco-sash.vertical > .orthogonal-drag-handle.end {
left: calc(var(--sash-size) / -2);
bottom: calc(var(--sash-size) * -1);
}
.monaco-sash.orthogonal-start.horizontal::before {
top: -calc(var(--sash-size) / 2);
.monaco-sash.horizontal > .orthogonal-drag-handle.start {
top: calc(var(--sash-size) / -2);
left: calc(var(--sash-size) * -1);
}
.monaco-sash.orthogonal-end.horizontal::after {
top: -calc(var(--sash-size) / 2);
.monaco-sash.horizontal > .orthogonal-drag-handle.end {
top: calc(var(--sash-size) / -2);
right: calc(var(--sash-size) * -1);
}
@@ -113,7 +116,6 @@
background: rgba(0, 255, 255, 0.2);
}
.monaco-sash.debug:not(.disabled).orthogonal-start::before,
.monaco-sash.debug:not(.disabled).orthogonal-end::after {
.monaco-sash.debug:not(.disabled) > .orthogonal-drag-handle {
background: red;
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./sash';
import { IDisposable, dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IDisposable, dispose, Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { isMacintosh } from 'vs/base/common/platform';
import * as types from 'vs/base/common/types';
import { EventType, GestureEvent, Gesture } from 'vs/base/browser/touch';
@@ -12,8 +12,10 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Event, Emitter } from 'vs/base/common/event';
import { getElementsByTagName, EventHelper, createStyleSheet, addDisposableListener, append, $ } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { Delayer } from 'vs/base/common/async';
const DEBUG = false;
let DEBUG = false;
// DEBUG = Boolean("true"); // done "weirdly" so that a lint warning prevents you from pushing this
export interface ISashLayoutProvider { }
@@ -86,6 +88,7 @@ export class Sash extends Disposable {
private hidden: boolean;
private orientation!: Orientation;
private size: number;
private hoverDelayer = this._register(new Delayer(300));
private _state: SashState = SashState.Enabled;
get state(): SashState { return this._state; }
@@ -121,15 +124,29 @@ export class Sash extends Disposable {
private readonly orthogonalStartSashDisposables = this._register(new DisposableStore());
private _orthogonalStartSash: Sash | undefined;
private readonly orthogonalStartDragHandleDisposables = this._register(new DisposableStore());
private _orthogonalStartDragHandle: HTMLElement | undefined;
get orthogonalStartSash(): Sash | undefined { return this._orthogonalStartSash; }
set orthogonalStartSash(sash: Sash | undefined) {
this.orthogonalStartDragHandleDisposables.clear();
this.orthogonalStartSashDisposables.clear();
if (sash) {
this.orthogonalStartSashDisposables.add(sash.onDidEnablementChange(this.onOrthogonalStartSashEnablementChange, this));
this.onOrthogonalStartSashEnablementChange(sash.state);
} else {
this.onOrthogonalStartSashEnablementChange(SashState.Disabled);
const onChange = (state: SashState) => {
this.orthogonalStartDragHandleDisposables.clear();
if (state !== SashState.Disabled) {
this._orthogonalStartDragHandle = append(this.el, $('.orthogonal-drag-handle.start'));
this.orthogonalStartDragHandleDisposables.add(toDisposable(() => this._orthogonalStartDragHandle!.remove()));
domEvent(this._orthogonalStartDragHandle, 'mouseenter')
(() => Sash.onMouseEnter(sash), undefined, this.orthogonalStartDragHandleDisposables);
domEvent(this._orthogonalStartDragHandle, 'mouseleave')
(() => Sash.onMouseLeave(sash), undefined, this.orthogonalStartDragHandleDisposables);
}
};
this.orthogonalStartSashDisposables.add(sash.onDidEnablementChange(onChange, this));
onChange(sash.state);
}
this._orthogonalStartSash = sash;
@@ -137,15 +154,29 @@ export class Sash extends Disposable {
private readonly orthogonalEndSashDisposables = this._register(new DisposableStore());
private _orthogonalEndSash: Sash | undefined;
private readonly orthogonalEndDragHandleDisposables = this._register(new DisposableStore());
private _orthogonalEndDragHandle: HTMLElement | undefined;
get orthogonalEndSash(): Sash | undefined { return this._orthogonalEndSash; }
set orthogonalEndSash(sash: Sash | undefined) {
this.orthogonalEndDragHandleDisposables.clear();
this.orthogonalEndSashDisposables.clear();
if (sash) {
this.orthogonalEndSashDisposables.add(sash.onDidEnablementChange(this.onOrthogonalEndSashEnablementChange, this));
this.onOrthogonalEndSashEnablementChange(sash.state);
} else {
this.onOrthogonalEndSashEnablementChange(SashState.Disabled);
const onChange = (state: SashState) => {
this.orthogonalEndDragHandleDisposables.clear();
if (state !== SashState.Disabled) {
this._orthogonalEndDragHandle = append(this.el, $('.orthogonal-drag-handle.end'));
this.orthogonalEndDragHandleDisposables.add(toDisposable(() => this._orthogonalEndDragHandle!.remove()));
domEvent(this._orthogonalEndDragHandle, 'mouseenter')
(() => Sash.onMouseEnter(sash), undefined, this.orthogonalEndDragHandleDisposables);
domEvent(this._orthogonalEndDragHandle, 'mouseleave')
(() => Sash.onMouseLeave(sash), undefined, this.orthogonalEndDragHandleDisposables);
}
};
this.orthogonalEndSashDisposables.add(sash.onDidEnablementChange(onChange, this));
onChange(sash.state);
}
this._orthogonalEndSash = sash;
@@ -168,6 +199,8 @@ export class Sash extends Disposable {
this._register(domEvent(this.el, 'mousedown')(this.onMouseDown, this));
this._register(domEvent(this.el, 'dblclick')(this.onMouseDoubleClick, this));
this._register(domEvent(this.el, 'mouseenter')(() => Sash.onMouseEnter(this)));
this._register(domEvent(this.el, 'mouseleave')(() => Sash.onMouseLeave(this)));
this._register(Gesture.addTarget(this.el));
this._register(domEvent(this.el, EventType.Start)(this.onTouchStart, this));
@@ -359,12 +392,34 @@ export class Sash extends Disposable {
}
}));
listeners.push(addDisposableListener(this.el, EventType.End, (event: GestureEvent) => {
listeners.push(addDisposableListener(this.el, EventType.End, () => {
this._onDidEnd.fire();
dispose(listeners);
}));
}
private static onMouseEnter(sash: Sash, fromLinkedSash: boolean = false): void {
if (sash.el.classList.contains('active')) {
sash.hoverDelayer.cancel();
sash.el.classList.add('hover');
} else {
sash.hoverDelayer.trigger(() => sash.el.classList.add('hover'));
}
if (!fromLinkedSash && sash.linkedSash) {
Sash.onMouseEnter(sash.linkedSash, true);
}
}
private static onMouseLeave(sash: Sash, fromLinkedSash: boolean = false): void {
sash.hoverDelayer.cancel();
sash.el.classList.remove('hover');
if (!fromLinkedSash && sash.linkedSash) {
Sash.onMouseLeave(sash.linkedSash, true);
}
}
layout(): void {
if (this.orientation === Orientation.VERTICAL) {
const verticalProvider = (<IVerticalSashLayoutProvider>this.layoutProvider);
@@ -407,27 +462,13 @@ export class Sash extends Disposable {
return this.hidden;
}
private onOrthogonalStartSashEnablementChange(state: SashState): void {
this.el.classList.toggle('orthogonal-start', state !== SashState.Disabled);
}
private onOrthogonalEndSashEnablementChange(state: SashState): void {
this.el.classList.toggle('orthogonal-end', state !== SashState.Disabled);
}
private getOrthogonalSash(e: MouseEvent): Sash | undefined {
if (this.orientation === Orientation.VERTICAL) {
if (e.offsetY <= this.size) {
return this.orthogonalStartSash;
} else if (e.offsetY >= this.el.clientHeight - this.size) {
return this.orthogonalEndSash;
}
} else {
if (e.offsetX <= this.size) {
return this.orthogonalStartSash;
} else if (e.offsetX >= this.el.clientWidth - this.size) {
return this.orthogonalEndSash;
}
if (!e.target || !(e.target instanceof HTMLElement)) {
return undefined;
}
if (e.target.classList.contains('orthogonal-drag-handle')) {
return e.target.classList.contains('start') ? this.orthogonalStartSash : this.orthogonalEndSash;
}
return undefined;

View File

@@ -736,8 +736,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Enter).on(e => this.onEnter(e), this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Escape).on(e => this.onEscape(e), this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.UpArrow).on(this.onUpArrow, this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.DownArrow).on(this.onDownArrow, this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.UpArrow).on(e => this.onUpArrow(e), this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.DownArrow).on(e => this.onDownArrow(e), this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.PageDown).on(this.onPageDown, this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.PageUp).on(this.onPageUp, this));
this._register(onSelectDropDownKeyDown.filter(e => e.keyCode === KeyCode.Home).on(this.onHome, this));
@@ -916,8 +916,9 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
}
// List navigation - have to handle a disabled option (jump over)
private onDownArrow(): void {
private onDownArrow(e: StandardKeyboardEvent): void {
if (this.selected < this.options.length - 1) {
dom.EventHelper.stop(e, true);
// Skip disabled options
const nextOptionDisabled = this.options[this.selected + 1].isDisabled;
@@ -937,8 +938,9 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
}
}
private onUpArrow(): void {
private onUpArrow(e: StandardKeyboardEvent): void {
if (this.selected > 0) {
dom.EventHelper.stop(e, true);
// Skip disabled options
const previousOptionDisabled = this.options[this.selected - 1].isDisabled;
if (previousOptionDisabled && this.selected > 1) {

View File

@@ -54,6 +54,7 @@
/* TODO: actions should be part of the pane, but they aren't yet */
.monaco-pane-view .pane:hover > .pane-header.expanded > .actions,
.monaco-pane-view .pane:focus-within > .pane-header.expanded > .actions,
.monaco-pane-view .pane > .pane-header.actions-always-visible.expanded > .actions,
.monaco-pane-view .pane > .pane-header.focused.expanded > .actions {
display: initial;

View File

@@ -432,7 +432,7 @@ export class PaneView extends Disposable {
private dnd: IPaneDndController | undefined;
private dndContext: IDndContext = { draggable: null };
private el: HTMLElement;
readonly element: HTMLElement;
private paneItems: IPaneItem[] = [];
private orthogonalSize: number = 0;
private size: number = 0;
@@ -450,8 +450,8 @@ export class PaneView extends Disposable {
this.dnd = options.dnd;
this.orientation = options.orientation ?? Orientation.VERTICAL;
this.el = append(container, $('.monaco-pane-view'));
this.splitview = this._register(new SplitView(this.el, { orientation: this.orientation }));
this.element = append(container, $('.monaco-pane-view'));
this.splitview = this._register(new SplitView(this.element, { orientation: this.orientation }));
this.onDidSashChange = this.splitview.onDidSashChange;
}
@@ -534,9 +534,9 @@ export class PaneView extends Disposable {
const paneSizes = this.paneItems.map(pane => this.getPaneSize(pane.pane));
this.splitview.dispose();
clearNode(this.el);
clearNode(this.element);
this.splitview = this._register(new SplitView(this.el, { orientation: this.orientation }));
this.splitview = this._register(new SplitView(this.element, { orientation: this.orientation }));
const newOrthogonalSize = this.orientation === Orientation.VERTICAL ? width : height;
const newSize = this.orientation === Orientation.HORIZONTAL ? width : height;
@@ -560,11 +560,11 @@ export class PaneView extends Disposable {
window.clearTimeout(this.animationTimer);
}
this.el.classList.add('animated');
this.element.classList.add('animated');
this.animationTimer = window.setTimeout(() => {
this.animationTimer = undefined;
this.el.classList.remove('animated');
this.element.classList.remove('animated');
}, 200);
}

View File

@@ -33,6 +33,8 @@ export interface ISplitViewOptions<TLayoutContext = undefined> {
readonly inverseAltBehavior?: boolean;
readonly proportionalLayout?: boolean; // default true,
readonly descriptor?: ISplitViewDescriptor<TLayoutContext>;
readonly scrollbarVisibility?: ScrollbarVisibility;
readonly getSashOrthogonalSize?: () => number;
}
/**
@@ -200,7 +202,7 @@ export namespace Sizing {
export function Invisible(cachedVisibleSize: number): InvisibleSizing { return { type: 'invisible', cachedVisibleSize }; }
}
export interface ISplitViewDescriptor<TLayoutContext> {
export interface ISplitViewDescriptor<TLayoutContext = undefined> {
size: number;
views: {
visible?: boolean;
@@ -227,6 +229,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
private state: State = State.Idle;
private inverseAltBehavior: boolean;
private proportionalLayout: boolean;
private readonly getSashOrthogonalSize: { (): number } | undefined;
private _onDidSashChange = this._register(new Emitter<number>());
readonly onDidSashChange = this._onDidSashChange.event;
@@ -298,6 +301,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation;
this.inverseAltBehavior = !!options.inverseAltBehavior;
this.proportionalLayout = types.isUndefined(options.proportionalLayout) ? true : !!options.proportionalLayout;
this.getSashOrthogonalSize = options.getSashOrthogonalSize;
this.el = document.createElement('div');
this.el.classList.add('monaco-split-view2');
@@ -309,8 +313,8 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
this.scrollable = new Scrollable(125, scheduleAtNextAnimationFrame);
this.scrollableElement = this._register(new SmoothScrollableElement(this.viewContainer, {
vertical: this.orientation === Orientation.VERTICAL ? ScrollbarVisibility.Auto : ScrollbarVisibility.Hidden,
horizontal: this.orientation === Orientation.HORIZONTAL ? ScrollbarVisibility.Auto : ScrollbarVisibility.Hidden
vertical: this.orientation === Orientation.VERTICAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden,
horizontal: this.orientation === Orientation.HORIZONTAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden
}, this.scrollable));
this._register(this.scrollableElement.onScroll(e => {
@@ -706,17 +710,11 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
// Add sash
if (this.viewItems.length > 1) {
let opts = { orthogonalStartSash: this.orthogonalStartSash, orthogonalEndSash: this.orthogonalEndSash };
const sash = this.orientation === Orientation.VERTICAL
? new Sash(this.sashContainer, { getHorizontalSashTop: (sash: Sash) => this.getSashPosition(sash) }, {
orientation: Orientation.HORIZONTAL,
orthogonalStartSash: this.orthogonalStartSash,
orthogonalEndSash: this.orthogonalEndSash
})
: new Sash(this.sashContainer, { getVerticalSashLeft: (sash: Sash) => this.getSashPosition(sash) }, {
orientation: Orientation.VERTICAL,
orthogonalStartSash: this.orthogonalStartSash,
orthogonalEndSash: this.orthogonalEndSash
});
? new Sash(this.sashContainer, { getHorizontalSashTop: s => this.getSashPosition(s), getHorizontalSashWidth: this.getSashOrthogonalSize }, { ...opts, orientation: Orientation.HORIZONTAL })
: new Sash(this.sashContainer, { getVerticalSashLeft: s => this.getSashPosition(s), getVerticalSashHeight: this.getSashOrthogonalSize }, { ...opts, orientation: Orientation.VERTICAL });
const sashEventMapper = this.orientation === Orientation.VERTICAL
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey })

View File

@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-table {
display: flex;
flex-direction: column;
position: relative;
height: 100%;
width: 100%;
white-space: nowrap;
}
.monaco-table > .monaco-split-view2 {
border-bottom: 1px solid transparent;
}
.monaco-table > .monaco-list {
flex: 1;
}
.monaco-table-tr {
display: flex;
}
.monaco-table-th {
width: 100%;
height: 100%;
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
}
.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;
left: calc(var(--sash-size) / 2);
width: 0;
border-left: 1px solid transparent;
}
.monaco-table > .monaco-split-view2,
.monaco-table > .monaco-split-view2 .monaco-sash.vertical::before {
transition: border-color 0.2s ease-out;
}
/*
.monaco-table:hover > .monaco-split-view2,
.monaco-table:hover > .monaco-split-view2 .monaco-sash.vertical::before {
border-color: rgba(204, 204, 204, 0.2);
} */

View File

@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IListContextMenuEvent, IListEvent, IListGestureEvent, IListMouseEvent, IListRenderer, IListTouchEvent } from 'vs/base/browser/ui/list/list';
import { Event } from 'vs/base/common/event';
export interface ITableColumn<TRow, TCell> {
readonly label: string;
readonly tooltip?: string;
readonly weight: number;
readonly templateId: string;
readonly minimumWidth?: number;
readonly maximumWidth?: number;
readonly onDidChangeWidthConstraints?: Event<void>;
project(row: TRow): TCell;
}
export interface ITableVirtualDelegate<TRow> {
readonly headerRowHeight: number;
getHeight(row: TRow): number;
}
export interface ITableRenderer<TCell, TTemplateData> extends IListRenderer<TCell, TTemplateData> { }
export interface ITableEvent<TRow> extends IListEvent<TRow> { }
export interface ITableMouseEvent<TRow> extends IListMouseEvent<TRow> { }
export interface ITableTouchEvent<TRow> extends IListTouchEvent<TRow> { }
export interface ITableGestureEvent<TRow> extends IListGestureEvent<TRow> { }
export interface ITableContextMenuEvent<TRow> extends IListContextMenuEvent<TRow> { }
export class TableError extends Error {
constructor(user: string, message: string) {
super(`TableError [${user}] ${message}`);
}
}

View File

@@ -0,0 +1,329 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./table';
import { IListOptions, IListOptionsUpdate, IListStyles, List } from 'vs/base/browser/ui/list/listWidget';
import { ITableColumn, ITableContextMenuEvent, ITableEvent, ITableGestureEvent, ITableMouseEvent, ITableRenderer, ITableTouchEvent, ITableVirtualDelegate } from 'vs/base/browser/ui/table/table';
import { ISpliceable } from 'vs/base/common/sequence';
import { IThemable } from 'vs/base/common/styler';
import { IDisposable } from 'vs/base/common/lifecycle';
import { $, append, clearNode, createStyleSheet, getContentHeight, getContentWidth } from 'vs/base/browser/dom';
import { ISplitViewDescriptor, IView, Orientation, SplitView } from 'vs/base/browser/ui/splitview/splitview';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { Emitter, Event } from 'vs/base/common/event';
import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
// TODO@joao
type TCell = any;
interface RowTemplateData {
readonly container: HTMLElement;
readonly cellContainers: HTMLElement[];
readonly cellTemplateData: unknown[];
}
class TableListRenderer<TRow> implements IListRenderer<TRow, RowTemplateData> {
static TemplateId = 'row';
readonly templateId = TableListRenderer.TemplateId;
private renderers: ITableRenderer<TCell, unknown>[];
private renderedTemplates = new Set<RowTemplateData>();
constructor(
private columns: ITableColumn<TRow, TCell>[],
renderers: ITableRenderer<TCell, unknown>[],
private getColumnSize: (index: number) => number
) {
const rendererMap = new Map(renderers.map(r => [r.templateId, r]));
this.renderers = [];
for (const column of columns) {
const renderer = rendererMap.get(column.templateId);
if (!renderer) {
throw new Error(`Table cell renderer for template id ${column.templateId} not found.`);
}
this.renderers.push(renderer);
}
}
renderTemplate(container: HTMLElement) {
const rowContainer = append(container, $('.monaco-table-tr'));
const cellContainers: HTMLElement[] = [];
const cellTemplateData: unknown[] = [];
for (let i = 0; i < this.columns.length; i++) {
const renderer = this.renderers[i];
const cellContainer = append(rowContainer, $('.monaco-table-td', { 'data-col-index': i }));
cellContainer.style.width = `${this.getColumnSize(i)}px`;
cellContainers.push(cellContainer);
cellTemplateData.push(renderer.renderTemplate(cellContainer));
}
const result = { container, cellContainers, cellTemplateData };
this.renderedTemplates.add(result);
return result;
}
renderElement(element: TRow, index: number, templateData: RowTemplateData, height: number | undefined): void {
for (let i = 0; i < this.columns.length; i++) {
const column = this.columns[i];
const cell = column.project(element);
const renderer = this.renderers[i];
renderer.renderElement(cell, index, templateData.cellTemplateData[i], height);
}
}
disposeElement(element: TRow, index: number, templateData: RowTemplateData, height: number | undefined): void {
for (let i = 0; i < this.columns.length; i++) {
const renderer = this.renderers[i];
if (renderer.disposeElement) {
const column = this.columns[i];
const cell = column.project(element);
renderer.disposeElement(cell, index, templateData.cellTemplateData[i], height);
}
}
}
disposeTemplate(templateData: RowTemplateData): void {
for (let i = 0; i < this.columns.length; i++) {
const renderer = this.renderers[i];
renderer.disposeTemplate(templateData.cellTemplateData[i]);
}
clearNode(templateData.container);
this.renderedTemplates.delete(templateData);
}
layoutColumn(index: number, size: number): void {
for (const { cellContainers } of this.renderedTemplates) {
cellContainers[index].style.width = `${size}px`;
}
}
}
function asListVirtualDelegate<TRow>(delegate: ITableVirtualDelegate<TRow>): IListVirtualDelegate<TRow> {
return {
getHeight(row) { return delegate.getHeight(row); },
getTemplateId() { return TableListRenderer.TemplateId; },
};
}
class ColumnHeader<TRow, TCell> implements IView {
readonly element: HTMLElement;
get minimumSize() { return this.column.minimumWidth ?? 120; }
get maximumSize() { return this.column.maximumWidth ?? Number.POSITIVE_INFINITY; }
get onDidChange() { return this.column.onDidChangeWidthConstraints ?? Event.None; }
private _onDidLayout = new Emitter<[number, number]>();
readonly onDidLayout = this._onDidLayout.event;
constructor(readonly column: ITableColumn<TRow, TCell>, private index: number) {
this.element = $('.monaco-table-th', { 'data-col-index': index, title: column.tooltip }, column.label);
}
layout(size: number): void {
this._onDidLayout.fire([this.index, size]);
}
}
export interface ITableOptions<TRow> extends IListOptions<TRow> { }
export interface ITableOptionsUpdate extends IListOptionsUpdate { }
export interface ITableStyles extends IListStyles { }
export class Table<TRow> implements ISpliceable<TRow>, IThemable, IDisposable {
private static InstanceCount = 0;
readonly domId = `table_id_${++Table.InstanceCount}`;
readonly domNode: HTMLElement;
private splitview: SplitView;
private list: List<TRow>;
private columnLayoutDisposable: IDisposable;
private cachedHeight: number = 0;
private styleElement: HTMLStyleElement;
get onDidChangeFocus(): Event<ITableEvent<TRow>> { return this.list.onDidChangeFocus; }
get onDidChangeSelection(): Event<ITableEvent<TRow>> { return this.list.onDidChangeSelection; }
get onDidScroll(): Event<ScrollEvent> { return this.list.onDidScroll; }
get onMouseClick(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseClick; }
get onMouseDblClick(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseDblClick; }
get onMouseMiddleClick(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseMiddleClick; }
get onPointer(): Event<ITableMouseEvent<TRow>> { return this.list.onPointer; }
get onMouseUp(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseUp; }
get onMouseDown(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseDown; }
get onMouseOver(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseOver; }
get onMouseMove(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseMove; }
get onMouseOut(): Event<ITableMouseEvent<TRow>> { return this.list.onMouseOut; }
get onTouchStart(): Event<ITableTouchEvent<TRow>> { return this.list.onTouchStart; }
get onTap(): Event<ITableGestureEvent<TRow>> { return this.list.onTap; }
get onContextMenu(): Event<ITableContextMenuEvent<TRow>> { return this.list.onContextMenu; }
get onDidFocus(): Event<void> { return this.list.onDidFocus; }
get onDidBlur(): Event<void> { return this.list.onDidBlur; }
get scrollTop(): number { return this.list.scrollTop; }
set scrollTop(scrollTop: number) { this.list.scrollTop = scrollTop; }
get scrollLeft(): number { return this.list.scrollLeft; }
set scrollLeft(scrollLeft: number) { this.list.scrollLeft = scrollLeft; }
get scrollHeight(): number { return this.list.scrollHeight; }
get renderHeight(): number { return this.list.renderHeight; }
get onDidDispose(): Event<void> { return this.list.onDidDispose; }
constructor(
user: string,
container: HTMLElement,
private virtualDelegate: ITableVirtualDelegate<TRow>,
columns: ITableColumn<TRow, TCell>[],
renderers: ITableRenderer<TCell, unknown>[],
_options?: ITableOptions<TRow>
) {
this.domNode = append(container, $(`.monaco-table.${this.domId}`));
const headers = columns.map((c, i) => new ColumnHeader(c, i));
const descriptor: ISplitViewDescriptor = {
size: headers.reduce((a, b) => a + b.column.weight, 0),
views: headers.map(view => ({ size: view.column.weight, view }))
};
this.splitview = new SplitView(this.domNode, {
orientation: Orientation.HORIZONTAL,
scrollbarVisibility: ScrollbarVisibility.Hidden,
getSashOrthogonalSize: () => this.cachedHeight,
descriptor
});
this.splitview.el.style.height = `${virtualDelegate.headerRowHeight}px`;
this.splitview.el.style.lineHeight = `${virtualDelegate.headerRowHeight}px`;
const renderer = new TableListRenderer(columns, renderers, i => this.splitview.getViewSize(i));
this.list = new List(user, this.domNode, asListVirtualDelegate(virtualDelegate), [renderer], _options);
this.columnLayoutDisposable = Event.any(...headers.map(h => h.onDidLayout))
(([index, size]) => renderer.layoutColumn(index, size));
this.styleElement = createStyleSheet(this.domNode);
this.style({});
}
updateOptions(options: ITableOptionsUpdate): void {
this.list.updateOptions(options);
}
splice(start: number, deleteCount: number, elements: TRow[] = []): void {
this.list.splice(start, deleteCount, elements);
}
rerender(): void {
this.list.rerender();
}
row(index: number): TRow {
return this.list.element(index);
}
indexOf(element: TRow): number {
return this.list.indexOf(element);
}
get length(): number {
return this.list.length;
}
getHTMLElement(): HTMLElement {
return this.domNode;
}
layout(height?: number, width?: number): void {
height = height ?? getContentHeight(this.domNode);
width = width ?? getContentWidth(this.domNode);
this.cachedHeight = height;
this.splitview.layout(width);
this.list.layout(height - this.virtualDelegate.headerRowHeight, width);
}
toggleKeyboardNavigation(): void {
this.list.toggleKeyboardNavigation();
}
style(styles: ITableStyles): void {
const content: string[] = [];
content.push(`.monaco-table.${this.domId} > .monaco-split-view2 .monaco-sash.vertical::before {
top: ${this.virtualDelegate.headerRowHeight + 1}px;
height: calc(100% - ${this.virtualDelegate.headerRowHeight}px);
}`);
this.styleElement.textContent = content.join('\n');
this.list.style(styles);
}
domFocus(): void {
this.list.domFocus();
}
getSelectedElements(): TRow[] {
return this.list.getSelectedElements();
}
setSelection(indexes: number[], browserEvent?: UIEvent): void {
this.list.setSelection(indexes, browserEvent);
}
getSelection(): number[] {
return this.list.getSelection();
}
setFocus(indexes: number[], browserEvent?: UIEvent): void {
this.list.setFocus(indexes, browserEvent);
}
focusNext(n = 1, loop = false, browserEvent?: UIEvent): void {
this.list.focusNext(n, loop, browserEvent);
}
focusPrevious(n = 1, loop = false, browserEvent?: UIEvent): void {
this.list.focusPrevious(n, loop, browserEvent);
}
focusNextPage(browserEvent?: UIEvent): void {
this.list.focusNextPage(browserEvent);
}
focusPreviousPage(browserEvent?: UIEvent): void {
this.list.focusPreviousPage(browserEvent);
}
focusFirst(browserEvent?: UIEvent): void {
this.list.focusFirst(browserEvent);
}
focusLast(browserEvent?: UIEvent): void {
this.list.focusLast(browserEvent);
}
getFocus(): number[] {
return this.list.getFocus();
}
reveal(index: number, relativeTop?: number): void {
this.list.reveal(index, relativeTop);
}
dispose(): void {
this.splitview.dispose();
this.list.dispose();
this.columnLayoutDisposable.dispose();
}
}

View File

@@ -5,8 +5,8 @@
import 'vs/css!./toolbar';
import * as nls from 'vs/nls';
import { Action, IActionRunner, IAction, IActionViewItemProvider, SubmenuAction } from 'vs/base/common/actions';
import { ActionBar, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action, IActionRunner, IAction, SubmenuAction } from 'vs/base/common/actions';
import { ActionBar, ActionsOrientation, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';

View File

@@ -961,7 +961,7 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions {
readonly filterOnType?: boolean;
readonly smoothScrolling?: boolean;
readonly horizontalScrolling?: boolean;
readonly expandOnlyOnDoubleClick?: boolean;
readonly expandOnDoubleClick?: boolean;
readonly expandOnlyOnTwistieClick?: boolean | ((e: any) => boolean); // e is T
}
@@ -1121,7 +1121,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
return super.onViewPointer(e);
}
if (this.tree.expandOnlyOnDoubleClick && e.browserEvent.detail !== 2 && !onTwistie) {
if (!this.tree.expandOnDoubleClick && e.browserEvent.detail === 2) {
return super.onViewPointer(e);
}
@@ -1129,6 +1129,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
const model = ((this.tree as any).model as ITreeModel<T, TFilterData, TRef>); // internal
const location = model.getNodeLocation(node);
const recursive = e.browserEvent.altKey;
this.tree.setFocus([location]);
model.setCollapsed(location, undefined, recursive);
if (expandOnlyOnTwistieClick && onTwistie) {
@@ -1142,7 +1143,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
protected onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
const onTwistie = (e.browserEvent.target as HTMLElement).classList.contains('monaco-tl-twistie');
if (onTwistie) {
if (onTwistie || !this.tree.expandOnDoubleClick) {
return;
}
@@ -1262,8 +1263,8 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
get filterOnType(): boolean { return !!this._options.filterOnType; }
get onDidChangeTypeFilterPattern(): Event<string> { return this.typeFilterController ? this.typeFilterController.onDidChangePattern : Event.None; }
get expandOnlyOnDoubleClick(): boolean { return this._options.expandOnlyOnDoubleClick ?? false; }
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? false : this._options.expandOnlyOnTwistieClick; }
get expandOnDoubleClick(): boolean { return typeof this._options.expandOnDoubleClick === 'undefined' ? true : this._options.expandOnDoubleClick; }
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? true : this._options.expandOnlyOnTwistieClick; }
private readonly _onDidUpdateOptions = new Emitter<IAbstractTreeOptions<T, TFilterData>>();
readonly onDidUpdateOptions: Event<IAbstractTreeOptions<T, TFilterData>> = this._onDidUpdateOptions.event;

View File

@@ -9,7 +9,7 @@ import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOve
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper, ITreeFilter, TreeVisibility, TreeFilterResult } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { timeout, CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
import { timeout, CancelablePromise, createCancelablePromise, Promises } from 'vs/base/common/async';
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
import { Iterable } from 'vs/base/common/iterator';
import { IDragAndDropData } from 'vs/base/browser/dnd';
@@ -740,7 +740,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
const childrenToRefresh = await this.doRefreshNode(node, recursive, viewStateContext);
node.stale = false;
await Promise.all(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext)));
await Promises.settled(childrenToRefresh.map(child => this.doRefreshSubTree(child, recursive, viewStateContext)));
} finally {
done!();
}
@@ -990,16 +990,16 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
const expanded: string[] = [];
const root = this.tree.getNode();
const queue = [root];
const stack = [root];
while (queue.length > 0) {
const node = queue.shift()!;
while (stack.length > 0) {
const node = stack.pop()!;
if (node !== root && node.collapsible && !node.collapsed) {
expanded.push(getId(node.element!.element as T));
}
queue.push(...node.children);
stack.push(...node.children);
}
return { focus, selection, expanded, scrollTop: this.scrollTop };

View File

@@ -56,6 +56,10 @@
overflow: hidden;
}
.monaco-tl-twistie::before {
border-radius: 20px;
}
.monaco-tl-twistie.collapsed::before {
transform: rotate(-90deg);
}

View File

@@ -69,7 +69,7 @@ export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends
this.model.updateElementHeight(element, height);
}
resort(element: T, recursive = true): void {
resort(element: T | null, recursive = true): void {
this.model.resort(element, recursive);
}

View File

@@ -39,19 +39,6 @@ export interface IActionRunner extends IDisposable {
readonly onBeforeRun: Event<IRunEvent>;
}
export interface IActionViewItem extends IDisposable {
actionRunner: IActionRunner;
setActionContext(context: any): void;
render(element: any /* HTMLElement */): void;
isEnabled(): boolean;
focus(fromRight?: boolean): void; // TODO@isidorn what is this?
blur(): void;
}
export interface IActionViewItemProvider {
(action: IAction): IActionViewItem | undefined;
}
export interface IActionChangeEvent {
readonly label?: string;
readonly tooltip?: string;
@@ -205,25 +192,6 @@ export class ActionRunner extends Disposable implements IActionRunner {
}
}
export class RadioGroup extends Disposable {
constructor(readonly actions: Action[]) {
super();
for (const action of actions) {
this._register(action.onDidChange(e => {
if (e.checked && action.checked) {
for (const candidate of actions) {
if (candidate !== action) {
candidate.checked = false;
}
}
}
}));
}
}
}
export class Separator extends Action {
static readonly ID = 'vs.actions.separator';
@@ -235,17 +203,6 @@ export class Separator extends Action {
}
}
export class ActionWithMenuAction extends Action {
get actions(): IAction[] {
return this._actions;
}
constructor(id: string, private _actions: IAction[], label?: string, cssClass?: string, enabled?: boolean, actionCallback?: (event?: any) => Promise<any>) {
super(id, label, cssClass, enabled, actionCallback);
}
}
export class SubmenuAction implements IAction {
readonly id: string;

View File

@@ -4,13 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
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 { URI } from 'vs/base/common/uri';
export function isThenable<T>(obj: any): obj is Promise<T> {
return obj && typeof (<Promise<any>>obj).then === 'function';
export function isThenable<T>(obj: unknown): obj is Promise<T> {
return !!obj && typeof (obj as unknown as Promise<T>).then === 'function';
}
export interface CancelablePromise<T> extends Promise<T> {
@@ -23,7 +24,7 @@ export function createCancelablePromise<T>(callback: (token: CancellationToken)
const thenable = callback(source.token);
const promise = new Promise<T>((resolve, reject) => {
source.token.onCancellationRequested(() => {
reject(errors.canceled());
reject(canceled());
});
Promise.resolve(thenable).then(value => {
source.dispose();
@@ -165,10 +166,10 @@ export class Throttler {
this.activePromise = promiseFactory();
return new Promise((resolve, reject) => {
this.activePromise!.then((result: any) => {
this.activePromise!.then((result: T) => {
this.activePromise = null;
resolve(result);
}, (err: any) => {
}, (err: unknown) => {
this.activePromise = null;
reject(err);
});
@@ -178,7 +179,7 @@ export class Throttler {
export class Sequencer {
private current: Promise<any> = Promise.resolve(null);
private current: Promise<unknown> = Promise.resolve(null);
queue<T>(promiseTask: ITask<Promise<T>>): Promise<T> {
return this.current = this.current.then(() => promiseTask(), () => promiseTask());
@@ -187,7 +188,7 @@ export class Sequencer {
export class SequencerByKey<TKey> {
private promiseMap = new Map<TKey, Promise<any>>();
private promiseMap = new Map<TKey, Promise<unknown>>();
queue<T>(key: TKey, promiseTask: ITask<Promise<T>>): Promise<T> {
const runningPromise = this.promiseMap.get(key) ?? Promise.resolve();
@@ -282,7 +283,7 @@ export class Delayer<T> implements IDisposable {
if (this.completionPromise) {
if (this.doReject) {
this.doReject(errors.canceled());
this.doReject(canceled());
}
this.completionPromise = null;
}
@@ -320,7 +321,7 @@ export class ThrottledDelayer<T> {
}
trigger(promiseFactory: ITask<Promise<T>>, delay?: number): Promise<T> {
return this.delayer.trigger(() => this.throttler.queue(promiseFactory), delay) as any as Promise<T>;
return this.delayer.trigger(() => this.throttler.queue(promiseFactory), delay) as unknown as Promise<T>;
}
isTriggered(): boolean {
@@ -366,6 +367,25 @@ export class Barrier {
}
}
/**
* A barrier that is initially closed and then becomes opened permanently after a certain period of
* time or when open is called explicitly
*/
export class AutoOpenBarrier extends Barrier {
private readonly _timeout: any;
constructor(autoOpenTimeMs: number) {
super();
this._timeout = setTimeout(() => this.open(), autoOpenTimeMs);
}
open(): void {
clearTimeout(this._timeout);
super.open();
}
}
export function timeout(millis: number): CancelablePromise<void>;
export function timeout(millis: number, token: CancellationToken): Promise<void>;
export function timeout(millis: number, token?: CancellationToken): CancelablePromise<void> | Promise<void> {
@@ -377,7 +397,7 @@ export function timeout(millis: number, token?: CancellationToken): CancelablePr
const handle = setTimeout(resolve, millis);
token.onCancellationRequested(() => {
clearTimeout(handle);
reject(errors.canceled());
reject(canceled());
});
});
}
@@ -487,7 +507,7 @@ export function firstParallel<T>(promiseList: Promise<T>[], shouldStop: (t: T) =
interface ILimitedTaskFactory<T> {
factory: ITask<Promise<T>>;
c: (value: T | Promise<T>) => void;
e: (error?: any) => void;
e: (error?: unknown) => void;
}
/**
@@ -666,7 +686,7 @@ export class IntervalTimer implements IDisposable {
export class RunOnceScheduler {
protected runner: ((...args: any[]) => void) | null;
protected runner: ((...args: unknown[]) => void) | null;
private timeoutToken: any;
private timeout: number;
@@ -826,7 +846,7 @@ export class IdleValue<T> {
private _didRun: boolean = false;
private _value?: T;
private _error: any;
private _error: unknown;
constructor(executor: () => T) {
this._executor = () => {
@@ -1014,7 +1034,9 @@ export class IntervalCounter {
//#endregion
export type ValueCallback<T = any> = (value: T | Promise<T>) => void;
//#region
export type ValueCallback<T = unknown> = (value: T | Promise<T>) => void;
/**
* Creates a promise whose resolution or rejection can be controlled imperatively.
@@ -1022,7 +1044,7 @@ export type ValueCallback<T = any> = (value: T | Promise<T>) => void;
export class DeferredPromise<T> {
private completeCallback!: ValueCallback<T>;
private errorCallback!: (err: any) => void;
private errorCallback!: (err: unknown) => void;
private rejected = false;
private resolved = false;
@@ -1055,7 +1077,7 @@ export class DeferredPromise<T> {
});
}
public error(err: any) {
public error(err: unknown) {
return new Promise<void>(resolve => {
this.errorCallback(err);
this.rejected = true;
@@ -1065,9 +1087,152 @@ export class DeferredPromise<T> {
public cancel() {
new Promise<void>(resolve => {
this.errorCallback(errors.canceled());
this.errorCallback(canceled());
this.rejected = true;
resolve();
});
}
}
//#endregion
//#region
export interface IWaitUntil {
waitUntil(thenable: Promise<unknown>): void;
}
export class AsyncEmitter<T extends IWaitUntil> extends Emitter<T> {
private _asyncDeliveryQueue?: LinkedList<[Listener<T>, Omit<T, 'waitUntil'>]>;
async fireAsync(data: Omit<T, 'waitUntil'>, token: CancellationToken, promiseJoin?: (p: Promise<unknown>, listener: Function) => Promise<unknown>): Promise<void> {
if (!this._listeners) {
return;
}
if (!this._asyncDeliveryQueue) {
this._asyncDeliveryQueue = new LinkedList();
}
for (const listener of this._listeners) {
this._asyncDeliveryQueue.push([listener, data]);
}
while (this._asyncDeliveryQueue.size > 0 && !token.isCancellationRequested) {
const [listener, data] = this._asyncDeliveryQueue.shift()!;
const thenables: Promise<unknown>[] = [];
const event = <T>{
...data,
waitUntil: (p: Promise<unknown>): void => {
if (Object.isFrozen(thenables)) {
throw new Error('waitUntil can NOT be called asynchronous');
}
if (promiseJoin) {
p = promiseJoin(p, typeof listener === 'function' ? listener : listener[0]);
}
thenables.push(p);
}
};
try {
if (typeof listener === 'function') {
listener.call(undefined, event);
} else {
listener[0].call(listener[1], event);
}
} catch (e) {
onUnexpectedError(e);
continue;
}
// freeze thenables-collection to enforce sync-calls to
// wait until and then wait for all thenables to resolve
Object.freeze(thenables);
await Promises.settled(thenables).catch(e => onUnexpectedError(e));
}
}
}
//#endregion
//#region Promises
export namespace Promises {
export interface IResolvedPromise<T> {
status: 'fulfilled';
value: T;
}
export interface IRejectedPromise {
status: 'rejected';
reason: Error;
}
/**
* Interface of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
*/
interface PromiseWithAllSettled<T> {
allSettled<T>(promises: Promise<T>[]): Promise<ReadonlyArray<IResolvedPromise<T> | IRejectedPromise>>;
}
/**
* A polyfill of `Promise.allSettled`: returns after all promises have
* resolved or rejected and provides access to each result or error
* in the order of the original passed in promises array.
* See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
*/
export async function allSettled<T>(promises: Promise<T>[]): Promise<ReadonlyArray<IResolvedPromise<T> | IRejectedPromise>> {
if (typeof (Promise as unknown as PromiseWithAllSettled<T>).allSettled === 'function') {
return allSettledNative(promises); // in some environments we can benefit from native implementation
}
return allSettledShim(promises);
}
async function allSettledNative<T>(promises: Promise<T>[]): Promise<ReadonlyArray<IResolvedPromise<T> | IRejectedPromise>> {
return (Promise as unknown as PromiseWithAllSettled<T>).allSettled(promises);
}
async function allSettledShim<T>(promises: Promise<T>[]): Promise<ReadonlyArray<IResolvedPromise<T> | IRejectedPromise>> {
return Promise.all(promises.map(promise => (promise.then(value => {
const fulfilled: IResolvedPromise<T> = { status: 'fulfilled', value };
return fulfilled;
}, error => {
const rejected: IRejectedPromise = { status: 'rejected', reason: error };
return rejected;
}))));
}
/**
* A drop-in replacement for `Promise.all` with the only difference
* that the method awaits every promise to either fulfill or reject.
*
* Similar to `Promise.all`, only the first error will be returned
* if any.
*/
export async function settled<T>(promises: Promise<T>[]): Promise<T[]> {
let firstError: Error | undefined = undefined;
const result = await Promise.all(promises.map(promise => promise.then(value => value, error => {
if (!firstError) {
firstError = error;
}
return undefined; // do not rethrow so that other promises can settle
})));
if (typeof firstError !== 'undefined') {
throw firstError;
}
return result as unknown as T[]; // cast is needed and protected by the `throw` above
}
}
//#endregion

View File

@@ -1,16 +0,0 @@
{
"name": "vs/base",
"dependencies": [
{
"name": "vs",
"internal": false
}
],
"libs": [
"lib.core.d.ts"
],
"sources": [
"**/*.ts"
],
"declares": []
}

View File

@@ -71,21 +71,26 @@ export interface CSSIcon {
readonly id: string;
}
export namespace CSSIcon {
export const iconIdRegex = /^(codicon\/)?([a-z\-]+)(?:~([a-z\-]+))?$/i;
export const iconNameSegment = '[A-Za-z0-9]+';
export const iconNameExpression = '[A-Za-z0-9\\-]+';
export const iconModifierExpression = '~[A-Za-z]+';
const cssIconIdRegex = new RegExp(`^(${iconNameExpression})(${iconModifierExpression})?$`);
export function asClassNameArray(icon: CSSIcon): string[] {
if (icon instanceof Codicon) {
return ['codicon', 'codicon-' + icon.id];
}
const match = iconIdRegex.exec(icon.id);
const match = cssIconIdRegex.exec(icon.id);
if (!match) {
return asClassNameArray(Codicon.error);
}
let [, , id, modifier] = match;
let [, id, modifier] = match;
const classNames = ['codicon', 'codicon-' + id];
if (modifier) {
classNames.push('codicon-modifier-' + modifier);
classNames.push('codicon-modifier-' + modifier.substr(1));
}
return classNames;
}
@@ -102,443 +107,447 @@ export namespace CSSIcon {
interface IconDefinition {
character: string;
fontCharacter: string;
}
export namespace Codicon {
// built-in icons, with image name
export const add = new Codicon('add', { character: '\\ea60' });
export const plus = new Codicon('plus', { character: '\\ea60' });
export const gistNew = new Codicon('gist-new', { character: '\\ea60' });
export const repoCreate = new Codicon('repo-create', { character: '\\ea60' });
export const lightbulb = new Codicon('lightbulb', { character: '\\ea61' });
export const lightBulb = new Codicon('light-bulb', { character: '\\ea61' });
export const repo = new Codicon('repo', { character: '\\ea62' });
export const repoDelete = new Codicon('repo-delete', { character: '\\ea62' });
export const gistFork = new Codicon('gist-fork', { character: '\\ea63' });
export const repoForked = new Codicon('repo-forked', { character: '\\ea63' });
export const gitPullRequest = new Codicon('git-pull-request', { character: '\\ea64' });
export const gitPullRequestAbandoned = new Codicon('git-pull-request-abandoned', { character: '\\ea64' });
export const recordKeys = new Codicon('record-keys', { character: '\\ea65' });
export const keyboard = new Codicon('keyboard', { character: '\\ea65' });
export const tag = new Codicon('tag', { character: '\\ea66' });
export const tagAdd = new Codicon('tag-add', { character: '\\ea66' });
export const tagRemove = new Codicon('tag-remove', { character: '\\ea66' });
export const person = new Codicon('person', { character: '\\ea67' });
export const personAdd = new Codicon('person-add', { character: '\\ea67' });
export const personFollow = new Codicon('person-follow', { character: '\\ea67' });
export const personOutline = new Codicon('person-outline', { character: '\\ea67' });
export const personFilled = new Codicon('person-filled', { character: '\\ea67' });
export const gitBranch = new Codicon('git-branch', { character: '\\ea68' });
export const gitBranchCreate = new Codicon('git-branch-create', { character: '\\ea68' });
export const gitBranchDelete = new Codicon('git-branch-delete', { character: '\\ea68' });
export const sourceControl = new Codicon('source-control', { character: '\\ea68' });
export const mirror = new Codicon('mirror', { character: '\\ea69' });
export const mirrorPublic = new Codicon('mirror-public', { character: '\\ea69' });
export const star = new Codicon('star', { character: '\\ea6a' });
export const starAdd = new Codicon('star-add', { character: '\\ea6a' });
export const starDelete = new Codicon('star-delete', { character: '\\ea6a' });
export const starEmpty = new Codicon('star-empty', { character: '\\ea6a' });
export const comment = new Codicon('comment', { character: '\\ea6b' });
export const commentAdd = new Codicon('comment-add', { character: '\\ea6b' });
export const alert = new Codicon('alert', { character: '\\ea6c' });
export const warning = new Codicon('warning', { character: '\\ea6c' });
export const search = new Codicon('search', { character: '\\ea6d' });
export const searchSave = new Codicon('search-save', { character: '\\ea6d' });
export const logOut = new Codicon('log-out', { character: '\\ea6e' });
export const signOut = new Codicon('sign-out', { character: '\\ea6e' });
export const logIn = new Codicon('log-in', { character: '\\ea6f' });
export const signIn = new Codicon('sign-in', { character: '\\ea6f' });
export const eye = new Codicon('eye', { character: '\\ea70' });
export const eyeUnwatch = new Codicon('eye-unwatch', { character: '\\ea70' });
export const eyeWatch = new Codicon('eye-watch', { character: '\\ea70' });
export const circleFilled = new Codicon('circle-filled', { character: '\\ea71' });
export const primitiveDot = new Codicon('primitive-dot', { character: '\\ea71' });
export const closeDirty = new Codicon('close-dirty', { character: '\\ea71' });
export const debugBreakpoint = new Codicon('debug-breakpoint', { character: '\\ea71' });
export const debugBreakpointDisabled = new Codicon('debug-breakpoint-disabled', { character: '\\ea71' });
export const debugHint = new Codicon('debug-hint', { character: '\\ea71' });
export const primitiveSquare = new Codicon('primitive-square', { character: '\\ea72' });
export const edit = new Codicon('edit', { character: '\\ea73' });
export const pencil = new Codicon('pencil', { character: '\\ea73' });
export const info = new Codicon('info', { character: '\\ea74' });
export const issueOpened = new Codicon('issue-opened', { character: '\\ea74' });
export const gistPrivate = new Codicon('gist-private', { character: '\\ea75' });
export const gitForkPrivate = new Codicon('git-fork-private', { character: '\\ea75' });
export const lock = new Codicon('lock', { character: '\\ea75' });
export const mirrorPrivate = new Codicon('mirror-private', { character: '\\ea75' });
export const close = new Codicon('close', { character: '\\ea76' });
export const removeClose = new Codicon('remove-close', { character: '\\ea76' });
export const x = new Codicon('x', { character: '\\ea76' });
export const repoSync = new Codicon('repo-sync', { character: '\\ea77' });
export const sync = new Codicon('sync', { character: '\\ea77' });
export const clone = new Codicon('clone', { character: '\\ea78' });
export const desktopDownload = new Codicon('desktop-download', { character: '\\ea78' });
export const beaker = new Codicon('beaker', { character: '\\ea79' });
export const microscope = new Codicon('microscope', { character: '\\ea79' });
export const vm = new Codicon('vm', { character: '\\ea7a' });
export const deviceDesktop = new Codicon('device-desktop', { character: '\\ea7a' });
export const file = new Codicon('file', { character: '\\ea7b' });
export const fileText = new Codicon('file-text', { character: '\\ea7b' });
export const more = new Codicon('more', { character: '\\ea7c' });
export const ellipsis = new Codicon('ellipsis', { character: '\\ea7c' });
export const kebabHorizontal = new Codicon('kebab-horizontal', { character: '\\ea7c' });
export const mailReply = new Codicon('mail-reply', { character: '\\ea7d' });
export const reply = new Codicon('reply', { character: '\\ea7d' });
export const organization = new Codicon('organization', { character: '\\ea7e' });
export const organizationFilled = new Codicon('organization-filled', { character: '\\ea7e' });
export const organizationOutline = new Codicon('organization-outline', { character: '\\ea7e' });
export const newFile = new Codicon('new-file', { character: '\\ea7f' });
export const fileAdd = new Codicon('file-add', { character: '\\ea7f' });
export const newFolder = new Codicon('new-folder', { character: '\\ea80' });
export const fileDirectoryCreate = new Codicon('file-directory-create', { character: '\\ea80' });
export const trash = new Codicon('trash', { character: '\\ea81' });
export const trashcan = new Codicon('trashcan', { character: '\\ea81' });
export const history = new Codicon('history', { character: '\\ea82' });
export const clock = new Codicon('clock', { character: '\\ea82' });
export const folder = new Codicon('folder', { character: '\\ea83' });
export const fileDirectory = new Codicon('file-directory', { character: '\\ea83' });
export const symbolFolder = new Codicon('symbol-folder', { character: '\\ea83' });
export const logoGithub = new Codicon('logo-github', { character: '\\ea84' });
export const markGithub = new Codicon('mark-github', { character: '\\ea84' });
export const github = new Codicon('github', { character: '\\ea84' });
export const terminal = new Codicon('terminal', { character: '\\ea85' });
export const console = new Codicon('console', { character: '\\ea85' });
export const repl = new Codicon('repl', { character: '\\ea85' });
export const zap = new Codicon('zap', { character: '\\ea86' });
export const symbolEvent = new Codicon('symbol-event', { character: '\\ea86' });
export const error = new Codicon('error', { character: '\\ea87' });
export const stop = new Codicon('stop', { character: '\\ea87' });
export const variable = new Codicon('variable', { character: '\\ea88' });
export const symbolVariable = new Codicon('symbol-variable', { character: '\\ea88' });
export const array = new Codicon('array', { character: '\\ea8a' });
export const symbolArray = new Codicon('symbol-array', { character: '\\ea8a' });
export const symbolModule = new Codicon('symbol-module', { character: '\\ea8b' });
export const symbolPackage = new Codicon('symbol-package', { character: '\\ea8b' });
export const symbolNamespace = new Codicon('symbol-namespace', { character: '\\ea8b' });
export const symbolObject = new Codicon('symbol-object', { character: '\\ea8b' });
export const symbolMethod = new Codicon('symbol-method', { character: '\\ea8c' });
export const symbolFunction = new Codicon('symbol-function', { character: '\\ea8c' });
export const symbolConstructor = new Codicon('symbol-constructor', { character: '\\ea8c' });
export const symbolBoolean = new Codicon('symbol-boolean', { character: '\\ea8f' });
export const symbolNull = new Codicon('symbol-null', { character: '\\ea8f' });
export const symbolNumeric = new Codicon('symbol-numeric', { character: '\\ea90' });
export const symbolNumber = new Codicon('symbol-number', { character: '\\ea90' });
export const symbolStructure = new Codicon('symbol-structure', { character: '\\ea91' });
export const symbolStruct = new Codicon('symbol-struct', { character: '\\ea91' });
export const symbolParameter = new Codicon('symbol-parameter', { character: '\\ea92' });
export const symbolTypeParameter = new Codicon('symbol-type-parameter', { character: '\\ea92' });
export const symbolKey = new Codicon('symbol-key', { character: '\\ea93' });
export const symbolText = new Codicon('symbol-text', { character: '\\ea93' });
export const symbolReference = new Codicon('symbol-reference', { character: '\\ea94' });
export const goToFile = new Codicon('go-to-file', { character: '\\ea94' });
export const symbolEnum = new Codicon('symbol-enum', { character: '\\ea95' });
export const symbolValue = new Codicon('symbol-value', { character: '\\ea95' });
export const symbolRuler = new Codicon('symbol-ruler', { character: '\\ea96' });
export const symbolUnit = new Codicon('symbol-unit', { character: '\\ea96' });
export const activateBreakpoints = new Codicon('activate-breakpoints', { character: '\\ea97' });
export const archive = new Codicon('archive', { character: '\\ea98' });
export const arrowBoth = new Codicon('arrow-both', { character: '\\ea99' });
export const arrowDown = new Codicon('arrow-down', { character: '\\ea9a' });
export const arrowLeft = new Codicon('arrow-left', { character: '\\ea9b' });
export const arrowRight = new Codicon('arrow-right', { character: '\\ea9c' });
export const arrowSmallDown = new Codicon('arrow-small-down', { character: '\\ea9d' });
export const arrowSmallLeft = new Codicon('arrow-small-left', { character: '\\ea9e' });
export const arrowSmallRight = new Codicon('arrow-small-right', { character: '\\ea9f' });
export const arrowSmallUp = new Codicon('arrow-small-up', { character: '\\eaa0' });
export const arrowUp = new Codicon('arrow-up', { character: '\\eaa1' });
export const bell = new Codicon('bell', { character: '\\eaa2' });
export const bold = new Codicon('bold', { character: '\\eaa3' });
export const book = new Codicon('book', { character: '\\eaa4' });
export const bookmark = new Codicon('bookmark', { character: '\\eaa5' });
export const debugBreakpointConditionalUnverified = new Codicon('debug-breakpoint-conditional-unverified', { character: '\\eaa6' });
export const debugBreakpointConditional = new Codicon('debug-breakpoint-conditional', { character: '\\eaa7' });
export const debugBreakpointConditionalDisabled = new Codicon('debug-breakpoint-conditional-disabled', { character: '\\eaa7' });
export const debugBreakpointDataUnverified = new Codicon('debug-breakpoint-data-unverified', { character: '\\eaa8' });
export const debugBreakpointData = new Codicon('debug-breakpoint-data', { character: '\\eaa9' });
export const debugBreakpointDataDisabled = new Codicon('debug-breakpoint-data-disabled', { character: '\\eaa9' });
export const debugBreakpointLogUnverified = new Codicon('debug-breakpoint-log-unverified', { character: '\\eaaa' });
export const debugBreakpointLog = new Codicon('debug-breakpoint-log', { character: '\\eaab' });
export const debugBreakpointLogDisabled = new Codicon('debug-breakpoint-log-disabled', { character: '\\eaab' });
export const briefcase = new Codicon('briefcase', { character: '\\eaac' });
export const broadcast = new Codicon('broadcast', { character: '\\eaad' });
export const browser = new Codicon('browser', { character: '\\eaae' });
export const bug = new Codicon('bug', { character: '\\eaaf' });
export const calendar = new Codicon('calendar', { character: '\\eab0' });
export const caseSensitive = new Codicon('case-sensitive', { character: '\\eab1' });
export const check = new Codicon('check', { character: '\\eab2' });
export const checklist = new Codicon('checklist', { character: '\\eab3' });
export const chevronDown = new Codicon('chevron-down', { character: '\\eab4' });
export const chevronLeft = new Codicon('chevron-left', { character: '\\eab5' });
export const chevronRight = new Codicon('chevron-right', { character: '\\eab6' });
export const chevronUp = new Codicon('chevron-up', { character: '\\eab7' });
export const chromeClose = new Codicon('chrome-close', { character: '\\eab8' });
export const chromeMaximize = new Codicon('chrome-maximize', { character: '\\eab9' });
export const chromeMinimize = new Codicon('chrome-minimize', { character: '\\eaba' });
export const chromeRestore = new Codicon('chrome-restore', { character: '\\eabb' });
export const circleOutline = new Codicon('circle-outline', { character: '\\eabc' });
export const debugBreakpointUnverified = new Codicon('debug-breakpoint-unverified', { character: '\\eabc' });
export const circleSlash = new Codicon('circle-slash', { character: '\\eabd' });
export const circuitBoard = new Codicon('circuit-board', { character: '\\eabe' });
export const clearAll = new Codicon('clear-all', { character: '\\eabf' });
export const clippy = new Codicon('clippy', { character: '\\eac0' });
export const closeAll = new Codicon('close-all', { character: '\\eac1' });
export const cloudDownload = new Codicon('cloud-download', { character: '\\eac2' });
export const cloudUpload = new Codicon('cloud-upload', { character: '\\eac3' });
export const code = new Codicon('code', { character: '\\eac4' });
export const collapseAll = new Codicon('collapse-all', { character: '\\eac5' });
export const colorMode = new Codicon('color-mode', { character: '\\eac6' });
export const commentDiscussion = new Codicon('comment-discussion', { character: '\\eac7' });
export const compareChanges = new Codicon('compare-changes', { character: '\\eafd' });
export const creditCard = new Codicon('credit-card', { character: '\\eac9' });
export const dash = new Codicon('dash', { character: '\\eacc' });
export const dashboard = new Codicon('dashboard', { character: '\\eacd' });
export const database = new Codicon('database', { character: '\\eace' });
export const debugContinue = new Codicon('debug-continue', { character: '\\eacf' });
export const debugDisconnect = new Codicon('debug-disconnect', { character: '\\ead0' });
export const debugPause = new Codicon('debug-pause', { character: '\\ead1' });
export const debugRestart = new Codicon('debug-restart', { character: '\\ead2' });
export const debugStart = new Codicon('debug-start', { character: '\\ead3' });
export const debugStepInto = new Codicon('debug-step-into', { character: '\\ead4' });
export const debugStepOut = new Codicon('debug-step-out', { character: '\\ead5' });
export const debugStepOver = new Codicon('debug-step-over', { character: '\\ead6' });
export const debugStop = new Codicon('debug-stop', { character: '\\ead7' });
export const debug = new Codicon('debug', { character: '\\ead8' });
export const deviceCameraVideo = new Codicon('device-camera-video', { character: '\\ead9' });
export const deviceCamera = new Codicon('device-camera', { character: '\\eada' });
export const deviceMobile = new Codicon('device-mobile', { character: '\\eadb' });
export const diffAdded = new Codicon('diff-added', { character: '\\eadc' });
export const diffIgnored = new Codicon('diff-ignored', { character: '\\eadd' });
export const diffModified = new Codicon('diff-modified', { character: '\\eade' });
export const diffRemoved = new Codicon('diff-removed', { character: '\\eadf' });
export const diffRenamed = new Codicon('diff-renamed', { character: '\\eae0' });
export const diff = new Codicon('diff', { character: '\\eae1' });
export const discard = new Codicon('discard', { character: '\\eae2' });
export const editorLayout = new Codicon('editor-layout', { character: '\\eae3' });
export const emptyWindow = new Codicon('empty-window', { character: '\\eae4' });
export const exclude = new Codicon('exclude', { character: '\\eae5' });
export const extensions = new Codicon('extensions', { character: '\\eae6' });
export const eyeClosed = new Codicon('eye-closed', { character: '\\eae7' });
export const fileBinary = new Codicon('file-binary', { character: '\\eae8' });
export const fileCode = new Codicon('file-code', { character: '\\eae9' });
export const fileMedia = new Codicon('file-media', { character: '\\eaea' });
export const filePdf = new Codicon('file-pdf', { character: '\\eaeb' });
export const fileSubmodule = new Codicon('file-submodule', { character: '\\eaec' });
export const fileSymlinkDirectory = new Codicon('file-symlink-directory', { character: '\\eaed' });
export const fileSymlinkFile = new Codicon('file-symlink-file', { character: '\\eaee' });
export const fileZip = new Codicon('file-zip', { character: '\\eaef' });
export const files = new Codicon('files', { character: '\\eaf0' });
export const filter = new Codicon('filter', { character: '\\eaf1' });
export const flame = new Codicon('flame', { character: '\\eaf2' });
export const foldDown = new Codicon('fold-down', { character: '\\eaf3' });
export const foldUp = new Codicon('fold-up', { character: '\\eaf4' });
export const fold = new Codicon('fold', { character: '\\eaf5' });
export const folderActive = new Codicon('folder-active', { character: '\\eaf6' });
export const folderOpened = new Codicon('folder-opened', { character: '\\eaf7' });
export const gear = new Codicon('gear', { character: '\\eaf8' });
export const gift = new Codicon('gift', { character: '\\eaf9' });
export const gistSecret = new Codicon('gist-secret', { character: '\\eafa' });
export const gist = new Codicon('gist', { character: '\\eafb' });
export const gitCommit = new Codicon('git-commit', { character: '\\eafc' });
export const gitCompare = new Codicon('git-compare', { character: '\\eafd' });
export const gitMerge = new Codicon('git-merge', { character: '\\eafe' });
export const githubAction = new Codicon('github-action', { character: '\\eaff' });
export const githubAlt = new Codicon('github-alt', { character: '\\eb00' });
export const globe = new Codicon('globe', { character: '\\eb01' });
export const grabber = new Codicon('grabber', { character: '\\eb02' });
export const graph = new Codicon('graph', { character: '\\eb03' });
export const gripper = new Codicon('gripper', { character: '\\eb04' });
export const heart = new Codicon('heart', { character: '\\eb05' });
export const home = new Codicon('home', { character: '\\eb06' });
export const horizontalRule = new Codicon('horizontal-rule', { character: '\\eb07' });
export const hubot = new Codicon('hubot', { character: '\\eb08' });
export const inbox = new Codicon('inbox', { character: '\\eb09' });
export const issueClosed = new Codicon('issue-closed', { character: '\\eb0a' });
export const issueReopened = new Codicon('issue-reopened', { character: '\\eb0b' });
export const issues = new Codicon('issues', { character: '\\eb0c' });
export const italic = new Codicon('italic', { character: '\\eb0d' });
export const jersey = new Codicon('jersey', { character: '\\eb0e' });
export const json = new Codicon('json', { character: '\\eb0f' });
export const kebabVertical = new Codicon('kebab-vertical', { character: '\\eb10' });
export const key = new Codicon('key', { character: '\\eb11' });
export const law = new Codicon('law', { character: '\\eb12' });
export const lightbulbAutofix = new Codicon('lightbulb-autofix', { character: '\\eb13' });
export const linkExternal = new Codicon('link-external', { character: '\\eb14' });
export const link = new Codicon('link', { character: '\\eb15' });
export const listOrdered = new Codicon('list-ordered', { character: '\\eb16' });
export const listUnordered = new Codicon('list-unordered', { character: '\\eb17' });
export const liveShare = new Codicon('live-share', { character: '\\eb18' });
export const loading = new Codicon('loading', { character: '\\eb19' });
export const location = new Codicon('location', { character: '\\eb1a' });
export const mailRead = new Codicon('mail-read', { character: '\\eb1b' });
export const mail = new Codicon('mail', { character: '\\eb1c' });
export const markdown = new Codicon('markdown', { character: '\\eb1d' });
export const megaphone = new Codicon('megaphone', { character: '\\eb1e' });
export const mention = new Codicon('mention', { character: '\\eb1f' });
export const milestone = new Codicon('milestone', { character: '\\eb20' });
export const mortarBoard = new Codicon('mortar-board', { character: '\\eb21' });
export const move = new Codicon('move', { character: '\\eb22' });
export const multipleWindows = new Codicon('multiple-windows', { character: '\\eb23' });
export const mute = new Codicon('mute', { character: '\\eb24' });
export const noNewline = new Codicon('no-newline', { character: '\\eb25' });
export const note = new Codicon('note', { character: '\\eb26' });
export const octoface = new Codicon('octoface', { character: '\\eb27' });
export const openPreview = new Codicon('open-preview', { character: '\\eb28' });
export const package_ = new Codicon('package', { character: '\\eb29' });
export const paintcan = new Codicon('paintcan', { character: '\\eb2a' });
export const pin = new Codicon('pin', { character: '\\eb2b' });
export const play = new Codicon('play', { character: '\\eb2c' });
export const run = new Codicon('run', { character: '\\eb2c' });
export const plug = new Codicon('plug', { character: '\\eb2d' });
export const preserveCase = new Codicon('preserve-case', { character: '\\eb2e' });
export const preview = new Codicon('preview', { character: '\\eb2f' });
export const project = new Codicon('project', { character: '\\eb30' });
export const pulse = new Codicon('pulse', { character: '\\eb31' });
export const question = new Codicon('question', { character: '\\eb32' });
export const quote = new Codicon('quote', { character: '\\eb33' });
export const radioTower = new Codicon('radio-tower', { character: '\\eb34' });
export const reactions = new Codicon('reactions', { character: '\\eb35' });
export const references = new Codicon('references', { character: '\\eb36' });
export const refresh = new Codicon('refresh', { character: '\\eb37' });
export const regex = new Codicon('regex', { character: '\\eb38' });
export const remoteExplorer = new Codicon('remote-explorer', { character: '\\eb39' });
export const remote = new Codicon('remote', { character: '\\eb3a' });
export const remove = new Codicon('remove', { character: '\\eb3b' });
export const replaceAll = new Codicon('replace-all', { character: '\\eb3c' });
export const replace = new Codicon('replace', { character: '\\eb3d' });
export const repoClone = new Codicon('repo-clone', { character: '\\eb3e' });
export const repoForcePush = new Codicon('repo-force-push', { character: '\\eb3f' });
export const repoPull = new Codicon('repo-pull', { character: '\\eb40' });
export const repoPush = new Codicon('repo-push', { character: '\\eb41' });
export const report = new Codicon('report', { character: '\\eb42' });
export const requestChanges = new Codicon('request-changes', { character: '\\eb43' });
export const rocket = new Codicon('rocket', { character: '\\eb44' });
export const rootFolderOpened = new Codicon('root-folder-opened', { character: '\\eb45' });
export const rootFolder = new Codicon('root-folder', { character: '\\eb46' });
export const rss = new Codicon('rss', { character: '\\eb47' });
export const ruby = new Codicon('ruby', { character: '\\eb48' });
export const saveAll = new Codicon('save-all', { character: '\\eb49' });
export const saveAs = new Codicon('save-as', { character: '\\eb4a' });
export const save = new Codicon('save', { character: '\\eb4b' });
export const screenFull = new Codicon('screen-full', { character: '\\eb4c' });
export const screenNormal = new Codicon('screen-normal', { character: '\\eb4d' });
export const searchStop = new Codicon('search-stop', { character: '\\eb4e' });
export const server = new Codicon('server', { character: '\\eb50' });
export const settingsGear = new Codicon('settings-gear', { character: '\\eb51' });
export const settings = new Codicon('settings', { character: '\\eb52' });
export const shield = new Codicon('shield', { character: '\\eb53' });
export const smiley = new Codicon('smiley', { character: '\\eb54' });
export const sortPrecedence = new Codicon('sort-precedence', { character: '\\eb55' });
export const splitHorizontal = new Codicon('split-horizontal', { character: '\\eb56' });
export const splitVertical = new Codicon('split-vertical', { character: '\\eb57' });
export const squirrel = new Codicon('squirrel', { character: '\\eb58' });
export const starFull = new Codicon('star-full', { character: '\\eb59' });
export const starHalf = new Codicon('star-half', { character: '\\eb5a' });
export const symbolClass = new Codicon('symbol-class', { character: '\\eb5b' });
export const symbolColor = new Codicon('symbol-color', { character: '\\eb5c' });
export const symbolConstant = new Codicon('symbol-constant', { character: '\\eb5d' });
export const symbolEnumMember = new Codicon('symbol-enum-member', { character: '\\eb5e' });
export const symbolField = new Codicon('symbol-field', { character: '\\eb5f' });
export const symbolFile = new Codicon('symbol-file', { character: '\\eb60' });
export const symbolInterface = new Codicon('symbol-interface', { character: '\\eb61' });
export const symbolKeyword = new Codicon('symbol-keyword', { character: '\\eb62' });
export const symbolMisc = new Codicon('symbol-misc', { character: '\\eb63' });
export const symbolOperator = new Codicon('symbol-operator', { character: '\\eb64' });
export const symbolProperty = new Codicon('symbol-property', { character: '\\eb65' });
export const wrench = new Codicon('wrench', { character: '\\eb65' });
export const wrenchSubaction = new Codicon('wrench-subaction', { character: '\\eb65' });
export const symbolSnippet = new Codicon('symbol-snippet', { character: '\\eb66' });
export const tasklist = new Codicon('tasklist', { character: '\\eb67' });
export const telescope = new Codicon('telescope', { character: '\\eb68' });
export const textSize = new Codicon('text-size', { character: '\\eb69' });
export const threeBars = new Codicon('three-bars', { character: '\\eb6a' });
export const thumbsdown = new Codicon('thumbsdown', { character: '\\eb6b' });
export const thumbsup = new Codicon('thumbsup', { character: '\\eb6c' });
export const tools = new Codicon('tools', { character: '\\eb6d' });
export const triangleDown = new Codicon('triangle-down', { character: '\\eb6e' });
export const triangleLeft = new Codicon('triangle-left', { character: '\\eb6f' });
export const triangleRight = new Codicon('triangle-right', { character: '\\eb70' });
export const triangleUp = new Codicon('triangle-up', { character: '\\eb71' });
export const twitter = new Codicon('twitter', { character: '\\eb72' });
export const unfold = new Codicon('unfold', { character: '\\eb73' });
export const unlock = new Codicon('unlock', { character: '\\eb74' });
export const unmute = new Codicon('unmute', { character: '\\eb75' });
export const unverified = new Codicon('unverified', { character: '\\eb76' });
export const verified = new Codicon('verified', { character: '\\eb77' });
export const versions = new Codicon('versions', { character: '\\eb78' });
export const vmActive = new Codicon('vm-active', { character: '\\eb79' });
export const vmOutline = new Codicon('vm-outline', { character: '\\eb7a' });
export const vmRunning = new Codicon('vm-running', { character: '\\eb7b' });
export const watch = new Codicon('watch', { character: '\\eb7c' });
export const whitespace = new Codicon('whitespace', { character: '\\eb7d' });
export const wholeWord = new Codicon('whole-word', { character: '\\eb7e' });
export const window = new Codicon('window', { character: '\\eb7f' });
export const wordWrap = new Codicon('word-wrap', { character: '\\eb80' });
export const zoomIn = new Codicon('zoom-in', { character: '\\eb81' });
export const zoomOut = new Codicon('zoom-out', { character: '\\eb82' });
export const listFilter = new Codicon('list-filter', { character: '\\eb83' });
export const listFlat = new Codicon('list-flat', { character: '\\eb84' });
export const listSelection = new Codicon('list-selection', { character: '\\eb85' });
export const selection = new Codicon('selection', { character: '\\eb85' });
export const listTree = new Codicon('list-tree', { character: '\\eb86' });
export const debugBreakpointFunctionUnverified = new Codicon('debug-breakpoint-function-unverified', { character: '\\eb87' });
export const debugBreakpointFunction = new Codicon('debug-breakpoint-function', { character: '\\eb88' });
export const debugBreakpointFunctionDisabled = new Codicon('debug-breakpoint-function-disabled', { character: '\\eb88' });
export const debugStackframeActive = new Codicon('debug-stackframe-active', { character: '\\eb89' });
export const debugStackframeDot = new Codicon('debug-stackframe-dot', { character: '\\eb8a' });
export const debugStackframe = new Codicon('debug-stackframe', { character: '\\eb8b' });
export const debugStackframeFocused = new Codicon('debug-stackframe-focused', { character: '\\eb8b' });
export const debugBreakpointUnsupported = new Codicon('debug-breakpoint-unsupported', { character: '\\eb8c' });
export const symbolString = new Codicon('symbol-string', { character: '\\eb8d' });
export const debugReverseContinue = new Codicon('debug-reverse-continue', { character: '\\eb8e' });
export const debugStepBack = new Codicon('debug-step-back', { character: '\\eb8f' });
export const debugRestartFrame = new Codicon('debug-restart-frame', { character: '\\eb90' });
export const callIncoming = new Codicon('call-incoming', { character: '\\eb92' });
export const callOutgoing = new Codicon('call-outgoing', { character: '\\eb93' });
export const menu = new Codicon('menu', { character: '\\eb94' });
export const expandAll = new Codicon('expand-all', { character: '\\eb95' });
export const feedback = new Codicon('feedback', { character: '\\eb96' });
export const groupByRefType = new Codicon('group-by-ref-type', { character: '\\eb97' });
export const ungroupByRefType = new Codicon('ungroup-by-ref-type', { character: '\\eb98' });
export const account = new Codicon('account', { character: '\\eb99' });
export const bellDot = new Codicon('bell-dot', { character: '\\eb9a' });
export const debugConsole = new Codicon('debug-console', { character: '\\eb9b' });
export const library = new Codicon('library', { character: '\\eb9c' });
export const output = new Codicon('output', { character: '\\eb9d' });
export const runAll = new Codicon('run-all', { character: '\\eb9e' });
export const syncIgnored = new Codicon('sync-ignored', { character: '\\eb9f' });
export const pinned = new Codicon('pinned', { character: '\\eba0' });
export const githubInverted = new Codicon('github-inverted', { character: '\\eba1' });
export const debugAlt = new Codicon('debug-alt', { character: '\\eb91' });
export const serverProcess = new Codicon('server-process', { character: '\\eba2' });
export const serverEnvironment = new Codicon('server-environment', { character: '\\eba3' });
export const pass = new Codicon('pass', { character: '\\eba4' });
export const stopCircle = new Codicon('stop-circle', { character: '\\eba5' });
export const playCircle = new Codicon('play-circle', { character: '\\eba6' });
export const record = new Codicon('record', { character: '\\eba7' });
export const debugAltSmall = new Codicon('debug-alt-small', { character: '\\eba8' });
export const vmConnect = new Codicon('vm-connect', { character: '\\eba9' });
export const cloud = new Codicon('cloud', { character: '\\ebaa' });
export const merge = new Codicon('merge', { character: '\\ebab' });
export const exportIcon = new Codicon('export', { character: '\\ebac' });
export const graphLeft = new Codicon('graph-left', { character: '\\ebad' });
export const magnet = new Codicon('magnet', { character: '\\ebae' });
export const notebook = new Codicon('notebook', { character: '\\ebaf' });
export const redo = new Codicon('redo', { character: '\\ebb0' });
export const checkAll = new Codicon('check-all', { character: '\\ebb1' });
export const pinnedDirty = new Codicon('pinned-dirty', { character: '\\ebb2' });
export const passFilled = new Codicon('pass-filled', { character: '\\ebb3' });
export const circleLargeFilled = new Codicon('circle-large-filled', { character: '\\ebb4' });
export const circleLargeOutline = new Codicon('circle-large-outline', { character: '\\ebb5' });
export const combine = new Codicon('combine', { character: '\\ebb6' });
export const gather = new Codicon('gather', { character: '\\ebb6' });
export const table = new Codicon('table', { character: '\\ebb7' });
export const variableGroup = new Codicon('variable-group', { character: '\\ebb8' });
export const typeHierarchy = new Codicon('type-hierarchy', { character: '\\ebb9' });
export const typeHierarchySub = new Codicon('type-hierarchy-sub', { character: '\\ebba' });
export const typeHierarchySuper = new Codicon('type-hierarchy-super', { character: '\\ebbb' });
export const gitPullRequestCreate = new Codicon('git-pull-request-create', { character: '\\ebbc' });
export const add = new Codicon('add', { fontCharacter: '\\ea60' });
export const plus = new Codicon('plus', { fontCharacter: '\\ea60' });
export const gistNew = new Codicon('gist-new', { fontCharacter: '\\ea60' });
export const repoCreate = new Codicon('repo-create', { fontCharacter: '\\ea60' });
export const lightbulb = new Codicon('lightbulb', { fontCharacter: '\\ea61' });
export const lightBulb = new Codicon('light-bulb', { fontCharacter: '\\ea61' });
export const repo = new Codicon('repo', { fontCharacter: '\\ea62' });
export const repoDelete = new Codicon('repo-delete', { fontCharacter: '\\ea62' });
export const gistFork = new Codicon('gist-fork', { fontCharacter: '\\ea63' });
export const repoForked = new Codicon('repo-forked', { fontCharacter: '\\ea63' });
export const gitPullRequest = new Codicon('git-pull-request', { fontCharacter: '\\ea64' });
export const gitPullRequestAbandoned = new Codicon('git-pull-request-abandoned', { fontCharacter: '\\ea64' });
export const recordKeys = new Codicon('record-keys', { fontCharacter: '\\ea65' });
export const keyboard = new Codicon('keyboard', { fontCharacter: '\\ea65' });
export const tag = new Codicon('tag', { fontCharacter: '\\ea66' });
export const tagAdd = new Codicon('tag-add', { fontCharacter: '\\ea66' });
export const tagRemove = new Codicon('tag-remove', { fontCharacter: '\\ea66' });
export const person = new Codicon('person', { fontCharacter: '\\ea67' });
export const personAdd = new Codicon('person-add', { fontCharacter: '\\ea67' });
export const personFollow = new Codicon('person-follow', { fontCharacter: '\\ea67' });
export const personOutline = new Codicon('person-outline', { fontCharacter: '\\ea67' });
export const personFilled = new Codicon('person-filled', { fontCharacter: '\\ea67' });
export const gitBranch = new Codicon('git-branch', { fontCharacter: '\\ea68' });
export const gitBranchCreate = new Codicon('git-branch-create', { fontCharacter: '\\ea68' });
export const gitBranchDelete = new Codicon('git-branch-delete', { fontCharacter: '\\ea68' });
export const sourceControl = new Codicon('source-control', { fontCharacter: '\\ea68' });
export const mirror = new Codicon('mirror', { fontCharacter: '\\ea69' });
export const mirrorPublic = new Codicon('mirror-public', { fontCharacter: '\\ea69' });
export const star = new Codicon('star', { fontCharacter: '\\ea6a' });
export const starAdd = new Codicon('star-add', { fontCharacter: '\\ea6a' });
export const starDelete = new Codicon('star-delete', { fontCharacter: '\\ea6a' });
export const starEmpty = new Codicon('star-empty', { fontCharacter: '\\ea6a' });
export const comment = new Codicon('comment', { fontCharacter: '\\ea6b' });
export const commentAdd = new Codicon('comment-add', { fontCharacter: '\\ea6b' });
export const alert = new Codicon('alert', { fontCharacter: '\\ea6c' });
export const warning = new Codicon('warning', { fontCharacter: '\\ea6c' });
export const search = new Codicon('search', { fontCharacter: '\\ea6d' });
export const searchSave = new Codicon('search-save', { fontCharacter: '\\ea6d' });
export const logOut = new Codicon('log-out', { fontCharacter: '\\ea6e' });
export const signOut = new Codicon('sign-out', { fontCharacter: '\\ea6e' });
export const logIn = new Codicon('log-in', { fontCharacter: '\\ea6f' });
export const signIn = new Codicon('sign-in', { fontCharacter: '\\ea6f' });
export const eye = new Codicon('eye', { fontCharacter: '\\ea70' });
export const eyeUnwatch = new Codicon('eye-unwatch', { fontCharacter: '\\ea70' });
export const eyeWatch = new Codicon('eye-watch', { fontCharacter: '\\ea70' });
export const circleFilled = new Codicon('circle-filled', { fontCharacter: '\\ea71' });
export const primitiveDot = new Codicon('primitive-dot', { fontCharacter: '\\ea71' });
export const closeDirty = new Codicon('close-dirty', { fontCharacter: '\\ea71' });
export const debugBreakpoint = new Codicon('debug-breakpoint', { fontCharacter: '\\ea71' });
export const debugBreakpointDisabled = new Codicon('debug-breakpoint-disabled', { fontCharacter: '\\ea71' });
export const debugHint = new Codicon('debug-hint', { fontCharacter: '\\ea71' });
export const primitiveSquare = new Codicon('primitive-square', { fontCharacter: '\\ea72' });
export const edit = new Codicon('edit', { fontCharacter: '\\ea73' });
export const pencil = new Codicon('pencil', { fontCharacter: '\\ea73' });
export const info = new Codicon('info', { fontCharacter: '\\ea74' });
export const issueOpened = new Codicon('issue-opened', { fontCharacter: '\\ea74' });
export const gistPrivate = new Codicon('gist-private', { fontCharacter: '\\ea75' });
export const gitForkPrivate = new Codicon('git-fork-private', { fontCharacter: '\\ea75' });
export const lock = new Codicon('lock', { fontCharacter: '\\ea75' });
export const mirrorPrivate = new Codicon('mirror-private', { fontCharacter: '\\ea75' });
export const close = new Codicon('close', { fontCharacter: '\\ea76' });
export const removeClose = new Codicon('remove-close', { fontCharacter: '\\ea76' });
export const x = new Codicon('x', { fontCharacter: '\\ea76' });
export const repoSync = new Codicon('repo-sync', { fontCharacter: '\\ea77' });
export const sync = new Codicon('sync', { fontCharacter: '\\ea77' });
export const clone = new Codicon('clone', { fontCharacter: '\\ea78' });
export const desktopDownload = new Codicon('desktop-download', { fontCharacter: '\\ea78' });
export const beaker = new Codicon('beaker', { fontCharacter: '\\ea79' });
export const microscope = new Codicon('microscope', { fontCharacter: '\\ea79' });
export const vm = new Codicon('vm', { fontCharacter: '\\ea7a' });
export const deviceDesktop = new Codicon('device-desktop', { fontCharacter: '\\ea7a' });
export const file = new Codicon('file', { fontCharacter: '\\ea7b' });
export const fileText = new Codicon('file-text', { fontCharacter: '\\ea7b' });
export const more = new Codicon('more', { fontCharacter: '\\ea7c' });
export const ellipsis = new Codicon('ellipsis', { fontCharacter: '\\ea7c' });
export const kebabHorizontal = new Codicon('kebab-horizontal', { fontCharacter: '\\ea7c' });
export const mailReply = new Codicon('mail-reply', { fontCharacter: '\\ea7d' });
export const reply = new Codicon('reply', { fontCharacter: '\\ea7d' });
export const organization = new Codicon('organization', { fontCharacter: '\\ea7e' });
export const organizationFilled = new Codicon('organization-filled', { fontCharacter: '\\ea7e' });
export const organizationOutline = new Codicon('organization-outline', { fontCharacter: '\\ea7e' });
export const newFile = new Codicon('new-file', { fontCharacter: '\\ea7f' });
export const fileAdd = new Codicon('file-add', { fontCharacter: '\\ea7f' });
export const newFolder = new Codicon('new-folder', { fontCharacter: '\\ea80' });
export const fileDirectoryCreate = new Codicon('file-directory-create', { fontCharacter: '\\ea80' });
export const trash = new Codicon('trash', { fontCharacter: '\\ea81' });
export const trashcan = new Codicon('trashcan', { fontCharacter: '\\ea81' });
export const history = new Codicon('history', { fontCharacter: '\\ea82' });
export const clock = new Codicon('clock', { fontCharacter: '\\ea82' });
export const folder = new Codicon('folder', { fontCharacter: '\\ea83' });
export const fileDirectory = new Codicon('file-directory', { fontCharacter: '\\ea83' });
export const symbolFolder = new Codicon('symbol-folder', { fontCharacter: '\\ea83' });
export const logoGithub = new Codicon('logo-github', { fontCharacter: '\\ea84' });
export const markGithub = new Codicon('mark-github', { fontCharacter: '\\ea84' });
export const github = new Codicon('github', { fontCharacter: '\\ea84' });
export const terminal = new Codicon('terminal', { fontCharacter: '\\ea85' });
export const console = new Codicon('console', { fontCharacter: '\\ea85' });
export const repl = new Codicon('repl', { fontCharacter: '\\ea85' });
export const zap = new Codicon('zap', { fontCharacter: '\\ea86' });
export const symbolEvent = new Codicon('symbol-event', { fontCharacter: '\\ea86' });
export const error = new Codicon('error', { fontCharacter: '\\ea87' });
export const stop = new Codicon('stop', { fontCharacter: '\\ea87' });
export const variable = new Codicon('variable', { fontCharacter: '\\ea88' });
export const symbolVariable = new Codicon('symbol-variable', { fontCharacter: '\\ea88' });
export const array = new Codicon('array', { fontCharacter: '\\ea8a' });
export const symbolArray = new Codicon('symbol-array', { fontCharacter: '\\ea8a' });
export const symbolModule = new Codicon('symbol-module', { fontCharacter: '\\ea8b' });
export const symbolPackage = new Codicon('symbol-package', { fontCharacter: '\\ea8b' });
export const symbolNamespace = new Codicon('symbol-namespace', { fontCharacter: '\\ea8b' });
export const symbolObject = new Codicon('symbol-object', { fontCharacter: '\\ea8b' });
export const symbolMethod = new Codicon('symbol-method', { fontCharacter: '\\ea8c' });
export const symbolFunction = new Codicon('symbol-function', { fontCharacter: '\\ea8c' });
export const symbolConstructor = new Codicon('symbol-constructor', { fontCharacter: '\\ea8c' });
export const symbolBoolean = new Codicon('symbol-boolean', { fontCharacter: '\\ea8f' });
export const symbolNull = new Codicon('symbol-null', { fontCharacter: '\\ea8f' });
export const symbolNumeric = new Codicon('symbol-numeric', { fontCharacter: '\\ea90' });
export const symbolNumber = new Codicon('symbol-number', { fontCharacter: '\\ea90' });
export const symbolStructure = new Codicon('symbol-structure', { fontCharacter: '\\ea91' });
export const symbolStruct = new Codicon('symbol-struct', { fontCharacter: '\\ea91' });
export const symbolParameter = new Codicon('symbol-parameter', { fontCharacter: '\\ea92' });
export const symbolTypeParameter = new Codicon('symbol-type-parameter', { fontCharacter: '\\ea92' });
export const symbolKey = new Codicon('symbol-key', { fontCharacter: '\\ea93' });
export const symbolText = new Codicon('symbol-text', { fontCharacter: '\\ea93' });
export const symbolReference = new Codicon('symbol-reference', { fontCharacter: '\\ea94' });
export const goToFile = new Codicon('go-to-file', { fontCharacter: '\\ea94' });
export const symbolEnum = new Codicon('symbol-enum', { fontCharacter: '\\ea95' });
export const symbolValue = new Codicon('symbol-value', { fontCharacter: '\\ea95' });
export const symbolRuler = new Codicon('symbol-ruler', { fontCharacter: '\\ea96' });
export const symbolUnit = new Codicon('symbol-unit', { fontCharacter: '\\ea96' });
export const activateBreakpoints = new Codicon('activate-breakpoints', { fontCharacter: '\\ea97' });
export const archive = new Codicon('archive', { fontCharacter: '\\ea98' });
export const arrowBoth = new Codicon('arrow-both', { fontCharacter: '\\ea99' });
export const arrowDown = new Codicon('arrow-down', { fontCharacter: '\\ea9a' });
export const arrowLeft = new Codicon('arrow-left', { fontCharacter: '\\ea9b' });
export const arrowRight = new Codicon('arrow-right', { fontCharacter: '\\ea9c' });
export const arrowSmallDown = new Codicon('arrow-small-down', { fontCharacter: '\\ea9d' });
export const arrowSmallLeft = new Codicon('arrow-small-left', { fontCharacter: '\\ea9e' });
export const arrowSmallRight = new Codicon('arrow-small-right', { fontCharacter: '\\ea9f' });
export const arrowSmallUp = new Codicon('arrow-small-up', { fontCharacter: '\\eaa0' });
export const arrowUp = new Codicon('arrow-up', { fontCharacter: '\\eaa1' });
export const bell = new Codicon('bell', { fontCharacter: '\\eaa2' });
export const bold = new Codicon('bold', { fontCharacter: '\\eaa3' });
export const book = new Codicon('book', { fontCharacter: '\\eaa4' });
export const bookmark = new Codicon('bookmark', { fontCharacter: '\\eaa5' });
export const debugBreakpointConditionalUnverified = new Codicon('debug-breakpoint-conditional-unverified', { fontCharacter: '\\eaa6' });
export const debugBreakpointConditional = new Codicon('debug-breakpoint-conditional', { fontCharacter: '\\eaa7' });
export const debugBreakpointConditionalDisabled = new Codicon('debug-breakpoint-conditional-disabled', { fontCharacter: '\\eaa7' });
export const debugBreakpointDataUnverified = new Codicon('debug-breakpoint-data-unverified', { fontCharacter: '\\eaa8' });
export const debugBreakpointData = new Codicon('debug-breakpoint-data', { fontCharacter: '\\eaa9' });
export const debugBreakpointDataDisabled = new Codicon('debug-breakpoint-data-disabled', { fontCharacter: '\\eaa9' });
export const debugBreakpointLogUnverified = new Codicon('debug-breakpoint-log-unverified', { fontCharacter: '\\eaaa' });
export const debugBreakpointLog = new Codicon('debug-breakpoint-log', { fontCharacter: '\\eaab' });
export const debugBreakpointLogDisabled = new Codicon('debug-breakpoint-log-disabled', { fontCharacter: '\\eaab' });
export const briefcase = new Codicon('briefcase', { fontCharacter: '\\eaac' });
export const broadcast = new Codicon('broadcast', { fontCharacter: '\\eaad' });
export const browser = new Codicon('browser', { fontCharacter: '\\eaae' });
export const bug = new Codicon('bug', { fontCharacter: '\\eaaf' });
export const calendar = new Codicon('calendar', { fontCharacter: '\\eab0' });
export const caseSensitive = new Codicon('case-sensitive', { fontCharacter: '\\eab1' });
export const check = new Codicon('check', { fontCharacter: '\\eab2' });
export const checklist = new Codicon('checklist', { fontCharacter: '\\eab3' });
export const chevronDown = new Codicon('chevron-down', { fontCharacter: '\\eab4' });
export const chevronLeft = new Codicon('chevron-left', { fontCharacter: '\\eab5' });
export const chevronRight = new Codicon('chevron-right', { fontCharacter: '\\eab6' });
export const chevronUp = new Codicon('chevron-up', { fontCharacter: '\\eab7' });
export const chromeClose = new Codicon('chrome-close', { fontCharacter: '\\eab8' });
export const chromeMaximize = new Codicon('chrome-maximize', { fontCharacter: '\\eab9' });
export const chromeMinimize = new Codicon('chrome-minimize', { fontCharacter: '\\eaba' });
export const chromeRestore = new Codicon('chrome-restore', { fontCharacter: '\\eabb' });
export const circleOutline = new Codicon('circle-outline', { fontCharacter: '\\eabc' });
export const debugBreakpointUnverified = new Codicon('debug-breakpoint-unverified', { fontCharacter: '\\eabc' });
export const circleSlash = new Codicon('circle-slash', { fontCharacter: '\\eabd' });
export const circuitBoard = new Codicon('circuit-board', { fontCharacter: '\\eabe' });
export const clearAll = new Codicon('clear-all', { fontCharacter: '\\eabf' });
export const clippy = new Codicon('clippy', { fontCharacter: '\\eac0' });
export const closeAll = new Codicon('close-all', { fontCharacter: '\\eac1' });
export const cloudDownload = new Codicon('cloud-download', { fontCharacter: '\\eac2' });
export const cloudUpload = new Codicon('cloud-upload', { fontCharacter: '\\eac3' });
export const code = new Codicon('code', { fontCharacter: '\\eac4' });
export const collapseAll = new Codicon('collapse-all', { fontCharacter: '\\eac5' });
export const colorMode = new Codicon('color-mode', { fontCharacter: '\\eac6' });
export const commentDiscussion = new Codicon('comment-discussion', { fontCharacter: '\\eac7' });
export const compareChanges = new Codicon('compare-changes', { fontCharacter: '\\eafd' });
export const creditCard = new Codicon('credit-card', { fontCharacter: '\\eac9' });
export const dash = new Codicon('dash', { fontCharacter: '\\eacc' });
export const dashboard = new Codicon('dashboard', { fontCharacter: '\\eacd' });
export const database = new Codicon('database', { fontCharacter: '\\eace' });
export const debugContinue = new Codicon('debug-continue', { fontCharacter: '\\eacf' });
export const debugDisconnect = new Codicon('debug-disconnect', { fontCharacter: '\\ead0' });
export const debugPause = new Codicon('debug-pause', { fontCharacter: '\\ead1' });
export const debugRestart = new Codicon('debug-restart', { fontCharacter: '\\ead2' });
export const debugStart = new Codicon('debug-start', { fontCharacter: '\\ead3' });
export const debugStepInto = new Codicon('debug-step-into', { fontCharacter: '\\ead4' });
export const debugStepOut = new Codicon('debug-step-out', { fontCharacter: '\\ead5' });
export const debugStepOver = new Codicon('debug-step-over', { fontCharacter: '\\ead6' });
export const debugStop = new Codicon('debug-stop', { fontCharacter: '\\ead7' });
export const debug = new Codicon('debug', { fontCharacter: '\\ead8' });
export const deviceCameraVideo = new Codicon('device-camera-video', { fontCharacter: '\\ead9' });
export const deviceCamera = new Codicon('device-camera', { fontCharacter: '\\eada' });
export const deviceMobile = new Codicon('device-mobile', { fontCharacter: '\\eadb' });
export const diffAdded = new Codicon('diff-added', { fontCharacter: '\\eadc' });
export const diffIgnored = new Codicon('diff-ignored', { fontCharacter: '\\eadd' });
export const diffModified = new Codicon('diff-modified', { fontCharacter: '\\eade' });
export const diffRemoved = new Codicon('diff-removed', { fontCharacter: '\\eadf' });
export const diffRenamed = new Codicon('diff-renamed', { fontCharacter: '\\eae0' });
export const diff = new Codicon('diff', { fontCharacter: '\\eae1' });
export const discard = new Codicon('discard', { fontCharacter: '\\eae2' });
export const editorLayout = new Codicon('editor-layout', { fontCharacter: '\\eae3' });
export const emptyWindow = new Codicon('empty-window', { fontCharacter: '\\eae4' });
export const exclude = new Codicon('exclude', { fontCharacter: '\\eae5' });
export const extensions = new Codicon('extensions', { fontCharacter: '\\eae6' });
export const eyeClosed = new Codicon('eye-closed', { fontCharacter: '\\eae7' });
export const fileBinary = new Codicon('file-binary', { fontCharacter: '\\eae8' });
export const fileCode = new Codicon('file-code', { fontCharacter: '\\eae9' });
export const fileMedia = new Codicon('file-media', { fontCharacter: '\\eaea' });
export const filePdf = new Codicon('file-pdf', { fontCharacter: '\\eaeb' });
export const fileSubmodule = new Codicon('file-submodule', { fontCharacter: '\\eaec' });
export const fileSymlinkDirectory = new Codicon('file-symlink-directory', { fontCharacter: '\\eaed' });
export const fileSymlinkFile = new Codicon('file-symlink-file', { fontCharacter: '\\eaee' });
export const fileZip = new Codicon('file-zip', { fontCharacter: '\\eaef' });
export const files = new Codicon('files', { fontCharacter: '\\eaf0' });
export const filter = new Codicon('filter', { fontCharacter: '\\eaf1' });
export const flame = new Codicon('flame', { fontCharacter: '\\eaf2' });
export const foldDown = new Codicon('fold-down', { fontCharacter: '\\eaf3' });
export const foldUp = new Codicon('fold-up', { fontCharacter: '\\eaf4' });
export const fold = new Codicon('fold', { fontCharacter: '\\eaf5' });
export const folderActive = new Codicon('folder-active', { fontCharacter: '\\eaf6' });
export const folderOpened = new Codicon('folder-opened', { fontCharacter: '\\eaf7' });
export const gear = new Codicon('gear', { fontCharacter: '\\eaf8' });
export const gift = new Codicon('gift', { fontCharacter: '\\eaf9' });
export const gistSecret = new Codicon('gist-secret', { fontCharacter: '\\eafa' });
export const gist = new Codicon('gist', { fontCharacter: '\\eafb' });
export const gitCommit = new Codicon('git-commit', { fontCharacter: '\\eafc' });
export const gitCompare = new Codicon('git-compare', { fontCharacter: '\\eafd' });
export const gitMerge = new Codicon('git-merge', { fontCharacter: '\\eafe' });
export const githubAction = new Codicon('github-action', { fontCharacter: '\\eaff' });
export const githubAlt = new Codicon('github-alt', { fontCharacter: '\\eb00' });
export const globe = new Codicon('globe', { fontCharacter: '\\eb01' });
export const grabber = new Codicon('grabber', { fontCharacter: '\\eb02' });
export const graph = new Codicon('graph', { fontCharacter: '\\eb03' });
export const gripper = new Codicon('gripper', { fontCharacter: '\\eb04' });
export const heart = new Codicon('heart', { fontCharacter: '\\eb05' });
export const home = new Codicon('home', { fontCharacter: '\\eb06' });
export const horizontalRule = new Codicon('horizontal-rule', { fontCharacter: '\\eb07' });
export const hubot = new Codicon('hubot', { fontCharacter: '\\eb08' });
export const inbox = new Codicon('inbox', { fontCharacter: '\\eb09' });
export const issueClosed = new Codicon('issue-closed', { fontCharacter: '\\eb0a' });
export const issueReopened = new Codicon('issue-reopened', { fontCharacter: '\\eb0b' });
export const issues = new Codicon('issues', { fontCharacter: '\\eb0c' });
export const italic = new Codicon('italic', { fontCharacter: '\\eb0d' });
export const jersey = new Codicon('jersey', { fontCharacter: '\\eb0e' });
export const json = new Codicon('json', { fontCharacter: '\\eb0f' });
export const kebabVertical = new Codicon('kebab-vertical', { fontCharacter: '\\eb10' });
export const key = new Codicon('key', { fontCharacter: '\\eb11' });
export const law = new Codicon('law', { fontCharacter: '\\eb12' });
export const lightbulbAutofix = new Codicon('lightbulb-autofix', { fontCharacter: '\\eb13' });
export const linkExternal = new Codicon('link-external', { fontCharacter: '\\eb14' });
export const link = new Codicon('link', { fontCharacter: '\\eb15' });
export const listOrdered = new Codicon('list-ordered', { fontCharacter: '\\eb16' });
export const listUnordered = new Codicon('list-unordered', { fontCharacter: '\\eb17' });
export const liveShare = new Codicon('live-share', { fontCharacter: '\\eb18' });
export const loading = new Codicon('loading', { fontCharacter: '\\eb19' });
export const location = new Codicon('location', { fontCharacter: '\\eb1a' });
export const mailRead = new Codicon('mail-read', { fontCharacter: '\\eb1b' });
export const mail = new Codicon('mail', { fontCharacter: '\\eb1c' });
export const markdown = new Codicon('markdown', { fontCharacter: '\\eb1d' });
export const megaphone = new Codicon('megaphone', { fontCharacter: '\\eb1e' });
export const mention = new Codicon('mention', { fontCharacter: '\\eb1f' });
export const milestone = new Codicon('milestone', { fontCharacter: '\\eb20' });
export const mortarBoard = new Codicon('mortar-board', { fontCharacter: '\\eb21' });
export const move = new Codicon('move', { fontCharacter: '\\eb22' });
export const multipleWindows = new Codicon('multiple-windows', { fontCharacter: '\\eb23' });
export const mute = new Codicon('mute', { fontCharacter: '\\eb24' });
export const noNewline = new Codicon('no-newline', { fontCharacter: '\\eb25' });
export const note = new Codicon('note', { fontCharacter: '\\eb26' });
export const octoface = new Codicon('octoface', { fontCharacter: '\\eb27' });
export const openPreview = new Codicon('open-preview', { fontCharacter: '\\eb28' });
export const package_ = new Codicon('package', { fontCharacter: '\\eb29' });
export const paintcan = new Codicon('paintcan', { fontCharacter: '\\eb2a' });
export const pin = new Codicon('pin', { fontCharacter: '\\eb2b' });
export const play = new Codicon('play', { fontCharacter: '\\eb2c' });
export const run = new Codicon('run', { fontCharacter: '\\eb2c' });
export const plug = new Codicon('plug', { fontCharacter: '\\eb2d' });
export const preserveCase = new Codicon('preserve-case', { fontCharacter: '\\eb2e' });
export const preview = new Codicon('preview', { fontCharacter: '\\eb2f' });
export const project = new Codicon('project', { fontCharacter: '\\eb30' });
export const pulse = new Codicon('pulse', { fontCharacter: '\\eb31' });
export const question = new Codicon('question', { fontCharacter: '\\eb32' });
export const quote = new Codicon('quote', { fontCharacter: '\\eb33' });
export const radioTower = new Codicon('radio-tower', { fontCharacter: '\\eb34' });
export const reactions = new Codicon('reactions', { fontCharacter: '\\eb35' });
export const references = new Codicon('references', { fontCharacter: '\\eb36' });
export const refresh = new Codicon('refresh', { fontCharacter: '\\eb37' });
export const regex = new Codicon('regex', { fontCharacter: '\\eb38' });
export const remoteExplorer = new Codicon('remote-explorer', { fontCharacter: '\\eb39' });
export const remote = new Codicon('remote', { fontCharacter: '\\eb3a' });
export const remove = new Codicon('remove', { fontCharacter: '\\eb3b' });
export const replaceAll = new Codicon('replace-all', { fontCharacter: '\\eb3c' });
export const replace = new Codicon('replace', { fontCharacter: '\\eb3d' });
export const repoClone = new Codicon('repo-clone', { fontCharacter: '\\eb3e' });
export const repoForcePush = new Codicon('repo-force-push', { fontCharacter: '\\eb3f' });
export const repoPull = new Codicon('repo-pull', { fontCharacter: '\\eb40' });
export const repoPush = new Codicon('repo-push', { fontCharacter: '\\eb41' });
export const report = new Codicon('report', { fontCharacter: '\\eb42' });
export const requestChanges = new Codicon('request-changes', { fontCharacter: '\\eb43' });
export const rocket = new Codicon('rocket', { fontCharacter: '\\eb44' });
export const rootFolderOpened = new Codicon('root-folder-opened', { fontCharacter: '\\eb45' });
export const rootFolder = new Codicon('root-folder', { fontCharacter: '\\eb46' });
export const rss = new Codicon('rss', { fontCharacter: '\\eb47' });
export const ruby = new Codicon('ruby', { fontCharacter: '\\eb48' });
export const saveAll = new Codicon('save-all', { fontCharacter: '\\eb49' });
export const saveAs = new Codicon('save-as', { fontCharacter: '\\eb4a' });
export const save = new Codicon('save', { fontCharacter: '\\eb4b' });
export const screenFull = new Codicon('screen-full', { fontCharacter: '\\eb4c' });
export const screenNormal = new Codicon('screen-normal', { fontCharacter: '\\eb4d' });
export const searchStop = new Codicon('search-stop', { fontCharacter: '\\eb4e' });
export const server = new Codicon('server', { fontCharacter: '\\eb50' });
export const settingsGear = new Codicon('settings-gear', { fontCharacter: '\\eb51' });
export const settings = new Codicon('settings', { fontCharacter: '\\eb52' });
export const shield = new Codicon('shield', { fontCharacter: '\\eb53' });
export const smiley = new Codicon('smiley', { fontCharacter: '\\eb54' });
export const sortPrecedence = new Codicon('sort-precedence', { fontCharacter: '\\eb55' });
export const splitHorizontal = new Codicon('split-horizontal', { fontCharacter: '\\eb56' });
export const splitVertical = new Codicon('split-vertical', { fontCharacter: '\\eb57' });
export const squirrel = new Codicon('squirrel', { fontCharacter: '\\eb58' });
export const starFull = new Codicon('star-full', { fontCharacter: '\\eb59' });
export const starHalf = new Codicon('star-half', { fontCharacter: '\\eb5a' });
export const symbolClass = new Codicon('symbol-class', { fontCharacter: '\\eb5b' });
export const symbolColor = new Codicon('symbol-color', { fontCharacter: '\\eb5c' });
export const symbolConstant = new Codicon('symbol-constant', { fontCharacter: '\\eb5d' });
export const symbolEnumMember = new Codicon('symbol-enum-member', { fontCharacter: '\\eb5e' });
export const symbolField = new Codicon('symbol-field', { fontCharacter: '\\eb5f' });
export const symbolFile = new Codicon('symbol-file', { fontCharacter: '\\eb60' });
export const symbolInterface = new Codicon('symbol-interface', { fontCharacter: '\\eb61' });
export const symbolKeyword = new Codicon('symbol-keyword', { fontCharacter: '\\eb62' });
export const symbolMisc = new Codicon('symbol-misc', { fontCharacter: '\\eb63' });
export const symbolOperator = new Codicon('symbol-operator', { fontCharacter: '\\eb64' });
export const symbolProperty = new Codicon('symbol-property', { fontCharacter: '\\eb65' });
export const wrench = new Codicon('wrench', { fontCharacter: '\\eb65' });
export const wrenchSubaction = new Codicon('wrench-subaction', { fontCharacter: '\\eb65' });
export const symbolSnippet = new Codicon('symbol-snippet', { fontCharacter: '\\eb66' });
export const tasklist = new Codicon('tasklist', { fontCharacter: '\\eb67' });
export const telescope = new Codicon('telescope', { fontCharacter: '\\eb68' });
export const textSize = new Codicon('text-size', { fontCharacter: '\\eb69' });
export const threeBars = new Codicon('three-bars', { fontCharacter: '\\eb6a' });
export const thumbsdown = new Codicon('thumbsdown', { fontCharacter: '\\eb6b' });
export const thumbsup = new Codicon('thumbsup', { fontCharacter: '\\eb6c' });
export const tools = new Codicon('tools', { fontCharacter: '\\eb6d' });
export const triangleDown = new Codicon('triangle-down', { fontCharacter: '\\eb6e' });
export const triangleLeft = new Codicon('triangle-left', { fontCharacter: '\\eb6f' });
export const triangleRight = new Codicon('triangle-right', { fontCharacter: '\\eb70' });
export const triangleUp = new Codicon('triangle-up', { fontCharacter: '\\eb71' });
export const twitter = new Codicon('twitter', { fontCharacter: '\\eb72' });
export const unfold = new Codicon('unfold', { fontCharacter: '\\eb73' });
export const unlock = new Codicon('unlock', { fontCharacter: '\\eb74' });
export const unmute = new Codicon('unmute', { fontCharacter: '\\eb75' });
export const unverified = new Codicon('unverified', { fontCharacter: '\\eb76' });
export const verified = new Codicon('verified', { fontCharacter: '\\eb77' });
export const versions = new Codicon('versions', { fontCharacter: '\\eb78' });
export const vmActive = new Codicon('vm-active', { fontCharacter: '\\eb79' });
export const vmOutline = new Codicon('vm-outline', { fontCharacter: '\\eb7a' });
export const vmRunning = new Codicon('vm-running', { fontCharacter: '\\eb7b' });
export const watch = new Codicon('watch', { fontCharacter: '\\eb7c' });
export const whitespace = new Codicon('whitespace', { fontCharacter: '\\eb7d' });
export const wholeWord = new Codicon('whole-word', { fontCharacter: '\\eb7e' });
export const window = new Codicon('window', { fontCharacter: '\\eb7f' });
export const wordWrap = new Codicon('word-wrap', { fontCharacter: '\\eb80' });
export const zoomIn = new Codicon('zoom-in', { fontCharacter: '\\eb81' });
export const zoomOut = new Codicon('zoom-out', { fontCharacter: '\\eb82' });
export const listFilter = new Codicon('list-filter', { fontCharacter: '\\eb83' });
export const listFlat = new Codicon('list-flat', { fontCharacter: '\\eb84' });
export const listSelection = new Codicon('list-selection', { fontCharacter: '\\eb85' });
export const selection = new Codicon('selection', { fontCharacter: '\\eb85' });
export const listTree = new Codicon('list-tree', { fontCharacter: '\\eb86' });
export const debugBreakpointFunctionUnverified = new Codicon('debug-breakpoint-function-unverified', { fontCharacter: '\\eb87' });
export const debugBreakpointFunction = new Codicon('debug-breakpoint-function', { fontCharacter: '\\eb88' });
export const debugBreakpointFunctionDisabled = new Codicon('debug-breakpoint-function-disabled', { fontCharacter: '\\eb88' });
export const debugStackframeActive = new Codicon('debug-stackframe-active', { fontCharacter: '\\eb89' });
export const debugStackframeDot = new Codicon('debug-stackframe-dot', { fontCharacter: '\\eb8a' });
export const debugStackframe = new Codicon('debug-stackframe', { fontCharacter: '\\eb8b' });
export const debugStackframeFocused = new Codicon('debug-stackframe-focused', { fontCharacter: '\\eb8b' });
export const debugBreakpointUnsupported = new Codicon('debug-breakpoint-unsupported', { fontCharacter: '\\eb8c' });
export const symbolString = new Codicon('symbol-string', { fontCharacter: '\\eb8d' });
export const debugReverseContinue = new Codicon('debug-reverse-continue', { fontCharacter: '\\eb8e' });
export const debugStepBack = new Codicon('debug-step-back', { fontCharacter: '\\eb8f' });
export const debugRestartFrame = new Codicon('debug-restart-frame', { fontCharacter: '\\eb90' });
export const callIncoming = new Codicon('call-incoming', { fontCharacter: '\\eb92' });
export const callOutgoing = new Codicon('call-outgoing', { fontCharacter: '\\eb93' });
export const menu = new Codicon('menu', { fontCharacter: '\\eb94' });
export const expandAll = new Codicon('expand-all', { fontCharacter: '\\eb95' });
export const feedback = new Codicon('feedback', { fontCharacter: '\\eb96' });
export const groupByRefType = new Codicon('group-by-ref-type', { fontCharacter: '\\eb97' });
export const ungroupByRefType = new Codicon('ungroup-by-ref-type', { fontCharacter: '\\eb98' });
export const account = new Codicon('account', { fontCharacter: '\\eb99' });
export const bellDot = new Codicon('bell-dot', { fontCharacter: '\\eb9a' });
export const debugConsole = new Codicon('debug-console', { fontCharacter: '\\eb9b' });
export const library = new Codicon('library', { fontCharacter: '\\eb9c' });
export const output = new Codicon('output', { fontCharacter: '\\eb9d' });
export const runAll = new Codicon('run-all', { fontCharacter: '\\eb9e' });
export const syncIgnored = new Codicon('sync-ignored', { fontCharacter: '\\eb9f' });
export const pinned = new Codicon('pinned', { fontCharacter: '\\eba0' });
export const githubInverted = new Codicon('github-inverted', { fontCharacter: '\\eba1' });
export const debugAlt = new Codicon('debug-alt', { fontCharacter: '\\eb91' });
export const serverProcess = new Codicon('server-process', { fontCharacter: '\\eba2' });
export const serverEnvironment = new Codicon('server-environment', { fontCharacter: '\\eba3' });
export const pass = new Codicon('pass', { fontCharacter: '\\eba4' });
export const stopCircle = new Codicon('stop-circle', { fontCharacter: '\\eba5' });
export const playCircle = new Codicon('play-circle', { fontCharacter: '\\eba6' });
export const record = new Codicon('record', { fontCharacter: '\\eba7' });
export const debugAltSmall = new Codicon('debug-alt-small', { fontCharacter: '\\eba8' });
export const vmConnect = new Codicon('vm-connect', { fontCharacter: '\\eba9' });
export const cloud = new Codicon('cloud', { fontCharacter: '\\ebaa' });
export const merge = new Codicon('merge', { fontCharacter: '\\ebab' });
export const exportIcon = new Codicon('export', { fontCharacter: '\\ebac' });
export const graphLeft = new Codicon('graph-left', { fontCharacter: '\\ebad' });
export const magnet = new Codicon('magnet', { fontCharacter: '\\ebae' });
export const notebook = new Codicon('notebook', { fontCharacter: '\\ebaf' });
export const redo = new Codicon('redo', { fontCharacter: '\\ebb0' });
export const checkAll = new Codicon('check-all', { fontCharacter: '\\ebb1' });
export const pinnedDirty = new Codicon('pinned-dirty', { fontCharacter: '\\ebb2' });
export const passFilled = new Codicon('pass-filled', { fontCharacter: '\\ebb3' });
export const circleLargeFilled = new Codicon('circle-large-filled', { fontCharacter: '\\ebb4' });
export const circleLargeOutline = new Codicon('circle-large-outline', { fontCharacter: '\\ebb5' });
export const combine = new Codicon('combine', { fontCharacter: '\\ebb6' });
export const gather = new Codicon('gather', { fontCharacter: '\\ebb6' });
export const table = new Codicon('table', { fontCharacter: '\\ebb7' });
export const variableGroup = new Codicon('variable-group', { fontCharacter: '\\ebb8' });
export const typeHierarchy = new Codicon('type-hierarchy', { fontCharacter: '\\ebb9' });
export const typeHierarchySub = new Codicon('type-hierarchy-sub', { fontCharacter: '\\ebba' });
export const typeHierarchySuper = new Codicon('type-hierarchy-super', { fontCharacter: '\\ebbb' });
export const gitPullRequestCreate = new Codicon('git-pull-request-create', { fontCharacter: '\\ebbc' });
export const runAbove = new Codicon('run-above', { fontCharacter: '\\ebbd' });
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 dropDownButton = new Codicon('drop-down-button', Codicon.chevronDown.definition);
}

View File

@@ -3,6 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IAction } from 'vs/base/common/actions';
export interface ErrorListenerCallback {
(error: any): void;
}
@@ -221,3 +223,31 @@ export class NotSupportedError extends Error {
}
}
}
export class ExpectedError extends Error {
readonly isExpected = true;
}
export interface IErrorOptions {
actions?: ReadonlyArray<IAction>;
}
export interface IErrorWithActions {
actions?: ReadonlyArray<IAction>;
}
export function isErrorWithActions(obj: unknown): obj is IErrorWithActions {
const candidate = obj as IErrorWithActions | undefined;
return candidate instanceof Error && Array.isArray(candidate.actions);
}
export function createErrorWithActions(message: string, options: IErrorOptions = Object.create(null)): Error & IErrorWithActions {
const result = new Error(message);
if (options.actions) {
(result as IErrorWithActions).actions = options.actions;
}
return result;
}

View File

@@ -1,28 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IAction } from 'vs/base/common/actions';
export interface IErrorOptions {
actions?: ReadonlyArray<IAction>;
}
export interface IErrorWithActions {
actions?: ReadonlyArray<IAction>;
}
export function isErrorWithActions(obj: unknown): obj is IErrorWithActions {
return obj instanceof Error && Array.isArray((obj as IErrorWithActions).actions);
}
export function createErrorWithActions(message: string, options: IErrorOptions = Object.create(null)): Error & IErrorWithActions {
const result = new Error(message);
if (options.actions) {
(<IErrorWithActions>result).actions = options.actions;
}
return result;
}

View File

@@ -7,7 +7,6 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { once as onceFn } from 'vs/base/common/functional';
import { Disposable, IDisposable, toDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { LinkedList } from 'vs/base/common/linkedList';
import { CancellationToken } from 'vs/base/common/cancellation';
import { StopWatch } from 'vs/base/common/stopwatch';
/**
@@ -379,7 +378,7 @@ export namespace Event {
}
}
type Listener<T> = [(e: T) => void, any] | ((e: T) => void);
export type Listener<T> = [(e: T) => void, any] | ((e: T) => void);
export interface EmitterOptions {
onFirstListenerAdd?: Function;
@@ -686,64 +685,6 @@ export class PauseableEmitter<T> extends Emitter<T> {
}
}
export interface IWaitUntil {
waitUntil(thenable: Promise<any>): void;
}
export class AsyncEmitter<T extends IWaitUntil> extends Emitter<T> {
private _asyncDeliveryQueue?: LinkedList<[Listener<T>, Omit<T, 'waitUntil'>]>;
async fireAsync(data: Omit<T, 'waitUntil'>, token: CancellationToken, promiseJoin?: (p: Promise<any>, listener: Function) => Promise<any>): Promise<void> {
if (!this._listeners) {
return;
}
if (!this._asyncDeliveryQueue) {
this._asyncDeliveryQueue = new LinkedList();
}
for (const listener of this._listeners) {
this._asyncDeliveryQueue.push([listener, data]);
}
while (this._asyncDeliveryQueue.size > 0 && !token.isCancellationRequested) {
const [listener, data] = this._asyncDeliveryQueue.shift()!;
const thenables: Promise<any>[] = [];
const event = <T>{
...data,
waitUntil: (p: Promise<any>): void => {
if (Object.isFrozen(thenables)) {
throw new Error('waitUntil can NOT be called asynchronous');
}
if (promiseJoin) {
p = promiseJoin(p, typeof listener === 'function' ? listener : listener[0]);
}
thenables.push(p);
}
};
try {
if (typeof listener === 'function') {
listener.call(undefined, event);
} else {
listener[0].call(listener[1], event);
}
} catch (e) {
onUnexpectedError(e);
continue;
}
// freeze thenables-collection to enforce sync-calls to
// wait until and then wait for all thenables to resolve
Object.freeze(thenables);
await Promise.all(thenables).catch(e => onUnexpectedError(e));
}
}
}
export class EventMultiplexer<T> implements IDisposable {
private readonly emitter: Emitter<T>;

View File

@@ -28,7 +28,6 @@ export function toSlashes(osPath: string) {
* or `getRoot('\\server\shares\path') === \\server\shares\`
*/
export function getRoot(path: string, sep: string = posix.sep): string {
if (!path) {
return '';
}

View File

@@ -547,8 +547,8 @@ export namespace FuzzyScore {
*/
export const Default: FuzzyScore = ([-100, 0]);
export function isDefault(score?: FuzzyScore): score is [-100, 0, 0] {
return !score || (score[0] === -100 && score[1] === 0 && score[2] === 0);
export function isDefault(score?: FuzzyScore): score is [-100, 0] {
return !score || (score.length === 2 && score[0] === -100 && score[1] === 0);
}
}

View File

@@ -3,28 +3,26 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CSSIcon } from 'vs/base/common/codicons';
import { matchesFuzzy, IMatch } from 'vs/base/common/filters';
import { ltrim } from 'vs/base/common/strings';
export const iconStartMarker = '$(';
const escapeIconsRegex = /(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)/gi;
const iconsRegex = new RegExp(`\\$\\(${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?\\)`, 'g'); // no capturing groups
const escapeIconsRegex = new RegExp(`(\\\\)?${iconsRegex.source}`, 'g');
export function escapeIcons(text: string): string {
return text.replace(escapeIconsRegex, (match, escaped) => escaped ? match : `\\${match}`);
}
const markdownEscapedIconsRegex = /\\\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)/gi;
const markdownEscapedIconsRegex = new RegExp(`\\\\${iconsRegex.source}`, 'g');
export function markdownEscapeEscapedIcons(text: string): string {
// Need to add an extra \ for escaping in markdown
return text.replace(markdownEscapedIconsRegex, match => `\\${match}`);
}
const markdownUnescapeIconsRegex = /(\\)?\$\\\(([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?)\\\)/gi;
export function markdownUnescapeIcons(text: string): string {
return text.replace(markdownUnescapeIconsRegex, (match, escaped, iconId) => escaped ? match : `$(${iconId})`);
}
const stripIconsRegex = /(\s)?(\\)?\$\([a-z0-9\-]+?(?:~[a-z0-9\-]*?)?\)(\s)?/gi;
const stripIconsRegex = new RegExp(`(\\s)?(\\\\)?${iconsRegex.source}(\\s)?`, 'g');
export function stripIcons(text: string): string {
if (text.indexOf(iconStartMarker) === -1) {
return text;

View File

@@ -39,6 +39,18 @@ export namespace Iterable {
return false;
}
export function find<T, R extends T>(iterable: Iterable<T>, predicate: (t: T) => t is R): T | undefined;
export function find<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): T | undefined;
export function find<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): T | undefined {
for (const element of iterable) {
if (predicate(element)) {
return element;
}
}
return undefined;
}
export function filter<T, R extends T>(iterable: Iterable<T>, predicate: (t: T) => t is R): Iterable<R>;
export function filter<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): Iterable<T>;
export function* filter<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): Iterable<T> {
@@ -71,22 +83,30 @@ export namespace Iterable {
}
}
export function reduce<T, R>(iterable: Iterable<T>, reducer: (previousValue: R, currentValue: T) => R, initialValue: R): R {
let value = initialValue;
for (const element of iterable) {
value = reducer(value, element);
}
return value;
}
/**
* Returns an iterable slice of the array, with the same semantics as `array.slice()`.
*/
export function* slice<T>(iterable: ReadonlyArray<T>, from: number, to = iterable.length): Iterable<T> {
export function* slice<T>(arr: ReadonlyArray<T>, from: number, to = arr.length): Iterable<T> {
if (from < 0) {
from += iterable.length;
from += arr.length;
}
if (to < 0) {
to += iterable.length;
} else if (to > iterable.length) {
to = iterable.length;
to += arr.length;
} else if (to > arr.length) {
to = arr.length;
}
for (; from < to; from++) {
yield iterable[from];
yield arr[from];
}
}
@@ -115,4 +135,25 @@ export namespace Iterable {
return [consumed, { [Symbol.iterator]() { return iterator; } }];
}
/**
* Returns whether the iterables are the same length and all items are
* equal using the comparator function.
*/
export function equals<T>(a: Iterable<T>, b: Iterable<T>, comparator = (at: T, bt: T) => at === bt) {
const ai = a[Symbol.iterator]();
const bi = b[Symbol.iterator]();
while (true) {
const an = ai.next();
const bn = bi.next();
if (an.done !== bn.done) {
return false;
} else if (an.done) {
return true;
} else if (!comparator(an.value, bn.value)) {
return false;
}
}
}
}

View File

@@ -597,6 +597,17 @@ export abstract class ResolvedKeybinding {
/**
* Returns the parts that should be used for dispatching.
* Returns null for parts consisting of only modifier keys
* @example keybinding "Shift" -> null
* @example keybinding ("D" with shift == true) -> "shift+D"
*/
public abstract getDispatchParts(): (string | null)[];
/**
* Returns the parts that should be used for dispatching single modifier keys
* Returns null for parts that contain more than one modifier or a regular key.
* @example keybinding "Shift" -> "shift"
* @example keybinding ("D" with shift == true") -> null
*/
public abstract getSingleModifierDispatchParts(): (string | null)[];
}

View File

@@ -68,7 +68,7 @@ export class MultiDisposeError extends Error {
constructor(
public readonly errors: any[]
) {
super(`Encounter errors while disposing of store. Errors: [${errors.join(', ')}]`);
super(`Encountered errors while disposing of store. Errors: [${errors.join(', ')}]`);
}
}
@@ -231,9 +231,7 @@ export class MutableDisposable<T extends IDisposable> implements IDisposable {
return;
}
if (this._value) {
this._value.dispose();
}
this._value?.dispose();
if (value) {
markTracked(value);
}
@@ -247,9 +245,7 @@ export class MutableDisposable<T extends IDisposable> implements IDisposable {
dispose(): void {
this._isDisposed = true;
markTracked(this);
if (this._value) {
this._value.dispose();
}
this._value?.dispose();
this._value = undefined;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -64,6 +64,8 @@ export namespace Schemas {
export const vscodeSettings = 'vscode-settings';
export const vscodeWorkspaceTrust = 'vscode-workspace-trust';
export const webviewPanel = 'webview-panel';
/**

View File

@@ -187,18 +187,3 @@ export function mapPager<T, R>(pager: IPager<T>, fn: (t: T) => R): IPager<R> {
getPage: (pageIndex, token) => pager.getPage(pageIndex, token).then(r => r.map(fn))
};
}
/**
* Merges two pagers.
*/
export function mergePagers<T>(one: IPager<T>, other: IPager<T>): IPager<T> {
return {
firstPage: [...one.firstPage, ...other.firstPage],
total: one.total + other.total,
pageSize: one.pageSize + other.pageSize,
getPage(pageIndex: number, token): Promise<T[]> {
return Promise.all([one.getPage(pageIndex, token), other.getPage(pageIndex, token)])
.then(([onePage, otherPage]) => [...onePage, ...otherPage]);
}
};
}

View File

@@ -235,7 +235,7 @@ export const setImmediate: ISetImmediate = (function defineSetImmediate() {
globals.postMessage({ vscodeSetImmediateId: myId }, '*');
};
}
if (nodeProcess) {
if (nodeProcess && typeof nodeProcess.nextTick === 'function') {
return nodeProcess.nextTick.bind(nodeProcess);
}
const _promise = Promise.resolve();

View File

@@ -42,8 +42,8 @@ export interface IExtUri {
/**
* Tests whether a `candidate` URI is a parent or equal of a given `base` URI.
*
* @param base A uri which is "longer"
* @param parentCandidate A uri which is "shorter" then `base`
* @param base A uri which is "longer" or at least same length as `parentCandidate`
* @param parentCandidate A uri which is "shorter" or up to same length as `base`
* @param ignoreFragment Ignore the fragment (defaults to `false`)
*/
isEqualOrParent(base: URI, parentCandidate: URI, ignoreFragment?: boolean): boolean;

View File

@@ -16,6 +16,13 @@ export interface ReadableStreamEvents<T> {
/**
* The 'data' event is emitted whenever the stream is
* relinquishing ownership of a chunk of data to a consumer.
*
* NOTE: PLEASE UNDERSTAND THAT ADDING A DATA LISTENER CAN
* TURN THE STREAM INTO FLOWING MODE. IT IS THEREFOR THE
* LAST LISTENER THAT SHOULD BE ADDED AND NOT THE FIRST
*
* Use `listenStream` as a helper method to listen to
* stream events in the right order.
*/
on(event: 'data', callback: (data: T) => void): void;
@@ -268,7 +275,7 @@ class WriteableStreamImpl<T> implements WriteableStream<T> {
// end with data or error if provided
if (result instanceof Error) {
this.error(result);
} else if (result) {
} else if (typeof result !== 'undefined') {
this.write(result);
}
@@ -489,22 +496,74 @@ export function peekReadable<T>(readable: Readable<T>, reducer: IReducer<T>, max
}
/**
* Helper to fully read a T stream into a T.
* Helper to fully read a T stream into a T or consuming
* a stream fully, awaiting all the events without caring
* about the data.
*/
export function consumeStream<T>(stream: ReadableStreamEvents<T>, reducer: IReducer<T>): Promise<T> {
export function consumeStream<T>(stream: ReadableStreamEvents<T>, reducer: IReducer<T>): Promise<T>;
export function consumeStream(stream: ReadableStreamEvents<unknown>): Promise<undefined>;
export function consumeStream<T>(stream: ReadableStreamEvents<T>, reducer?: IReducer<T>): Promise<T | undefined> {
return new Promise((resolve, reject) => {
const chunks: T[] = [];
stream.on('error', error => reject(error));
stream.on('end', () => resolve(reducer(chunks)));
// Adding the `data` listener will turn the stream
// into flowing mode. As such it is important to
// add this listener last (DO NOT CHANGE!)
stream.on('data', data => chunks.push(data));
listenStream(stream, {
onData: chunk => {
if (reducer) {
chunks.push(chunk);
}
},
onError: error => {
if (reducer) {
reject(error);
} else {
resolve(undefined);
}
},
onEnd: () => {
if (reducer) {
resolve(reducer(chunks));
} else {
resolve(undefined);
}
}
});
});
}
export interface IStreamListener<T> {
/**
* The 'data' event is emitted whenever the stream is
* relinquishing ownership of a chunk of data to a consumer.
*/
onData(data: T): void;
/**
* Emitted when any error occurs.
*/
onError(err: Error): void;
/**
* The 'end' event is emitted when there is no more data
* to be consumed from the stream. The 'end' event will
* not be emitted unless the data is completely consumed.
*/
onEnd(): void;
}
/**
* Helper to listen to all events of a T stream in proper order.
*/
export function listenStream<T>(stream: ReadableStreamEvents<T>, listener: IStreamListener<T>): void {
stream.on('error', error => listener.onError(error));
stream.on('end', () => listener.onEnd());
// Adding the `data` listener will turn the stream
// into flowing mode. As such it is important to
// add this listener last (DO NOT CHANGE!)
stream.on('data', data => listener.onData(data));
}
/**
* Helper to peek up to `maxChunks` into a stream. The return type signals if
* the stream has ended or not. If not, caller needs to add a `data` listener
@@ -513,9 +572,9 @@ export function consumeStream<T>(stream: ReadableStreamEvents<T>, reducer: IRedu
export function peekStream<T>(stream: ReadableStream<T>, maxChunks: number): Promise<ReadableBufferedStream<T>> {
return new Promise((resolve, reject) => {
const streamListeners = new DisposableStore();
const buffer: T[] = [];
// Data Listener
const buffer: T[] = [];
const dataListener = (chunk: T) => {
// Add to buffer
@@ -533,23 +592,27 @@ export function peekStream<T>(stream: ReadableStream<T>, maxChunks: number): Pro
}
};
streamListeners.add(toDisposable(() => stream.removeListener('data', dataListener)));
stream.on('data', dataListener);
// Error Listener
const errorListener = (error: Error) => {
return reject(error);
};
streamListeners.add(toDisposable(() => stream.removeListener('error', errorListener)));
stream.on('error', errorListener);
// End Listener
const endListener = () => {
return resolve({ stream, buffer, ended: true });
};
streamListeners.add(toDisposable(() => stream.removeListener('error', errorListener)));
stream.on('error', errorListener);
streamListeners.add(toDisposable(() => stream.removeListener('end', endListener)));
stream.on('end', endListener);
// Important: leave the `data` listener last because
// this can turn the stream into flowing mode and we
// want `error` events to be received as well.
streamListeners.add(toDisposable(() => stream.removeListener('data', dataListener)));
stream.on('data', dataListener);
});
}
@@ -589,46 +652,11 @@ export function toReadable<T>(t: T): Readable<T> {
export function transform<Original, Transformed>(stream: ReadableStreamEvents<Original>, transformer: ITransformer<Original, Transformed>, reducer: IReducer<Transformed>): ReadableStream<Transformed> {
const target = newWriteableStream<Transformed>(reducer);
stream.on('data', data => target.write(transformer.data(data)));
stream.on('end', () => target.end());
stream.on('error', error => target.error(transformer.error ? transformer.error(error) : error));
listenStream(stream, {
onData: data => target.write(transformer.data(data)),
onError: error => target.error(transformer.error ? transformer.error(error) : error),
onEnd: () => target.end()
});
return target;
}
export interface IReadableStreamObservable {
/**
* A promise to await the `end` or `error` event
* of a stream.
*/
errorOrEnd: () => Promise<void>;
}
/**
* Helper to observe a stream for certain events through
* a promise based API.
*/
export function observe(stream: ReadableStream<unknown>): IReadableStreamObservable {
// A stream is closed when it ended or errord
// We install this listener right from the
// beginning to catch the events early.
const errorOrEnd = Promise.race([
new Promise<void>(resolve => stream.on('end', () => resolve())),
new Promise<void>(resolve => stream.on('error', () => resolve()))
]);
return {
errorOrEnd(): Promise<void> {
// We need to ensure the stream is flowing so that our
// listeners are getting triggered. It is possible that
// the stream is not flowing because no `data` listener
// was attached yet.
stream.resume();
return errorOrEnd;
}
};
}

File diff suppressed because one or more lines are too long

View File

@@ -8,22 +8,22 @@ import { URI, UriComponents } from 'vs/base/common/uri';
/**
* @returns whether the provided parameter is a JavaScript Array or not.
*/
export function isArray<T>(array: T | {}): array is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[] {
export function isArray(array: any): array is any[] {
return Array.isArray(array);
}
/**
* @returns whether the provided parameter is a JavaScript String or not.
*/
export function isString(str: any): str is string {
export function isString(str: unknown): str is string {
return (typeof str === 'string');
}
/**
* @returns whether the provided parameter is a JavaScript Array and each element in the array is a string.
*/
export function isStringArray(value: any): value is string[] {
return Array.isArray(value) && (<any[]>value).every(elem => isString(elem));
export function isStringArray(value: unknown): value is string[] {
return Array.isArray(value) && (<unknown[]>value).every(elem => isString(elem));
}
/**
@@ -31,7 +31,7 @@ export function isStringArray(value: any): value is string[] {
* @returns whether the provided parameter is of type `object` but **not**
* `null`, an `array`, a `regexp`, nor a `date`.
*/
export function isObject(obj: any): obj is Object {
export function isObject(obj: unknown): obj is Object {
// The method can't do a type cast since there are type (like strings) which
// are subclasses of any put not positvely matched by the function. Hence type
// narrowing results in wrong results.
@@ -46,21 +46,21 @@ export function isObject(obj: any): obj is Object {
* In **contrast** to just checking `typeof` this will return `false` for `NaN`.
* @returns whether the provided parameter is a JavaScript Number or not.
*/
export function isNumber(obj: any): obj is number {
export function isNumber(obj: unknown): obj is number {
return (typeof obj === 'number' && !isNaN(obj));
}
/**
* @returns whether the provided parameter is a JavaScript Boolean or not.
*/
export function isBoolean(obj: any): obj is boolean {
export function isBoolean(obj: unknown): obj is boolean {
return (obj === true || obj === false);
}
/**
* @returns whether the provided parameter is undefined.
*/
export function isUndefined(obj: any): obj is undefined {
export function isUndefined(obj: unknown): obj is undefined {
return (typeof obj === 'undefined');
}
@@ -74,12 +74,12 @@ export function isDefined<T>(arg: T | null | undefined): arg is T {
/**
* @returns whether the provided parameter is undefined or null.
*/
export function isUndefinedOrNull(obj: any): obj is undefined | null {
export function isUndefinedOrNull(obj: unknown): obj is undefined | null {
return (isUndefined(obj) || obj === null);
}
export function assertType(condition: any, type?: string): asserts condition {
export function assertType(condition: unknown, type?: string): asserts condition {
if (!condition) {
throw new Error(type ? `Unexpected type, expected '${type}'` : 'Unexpected type');
}
@@ -123,7 +123,7 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* @returns whether the provided parameter is an empty JavaScript Object or not.
*/
export function isEmptyObject(obj: any): obj is any {
export function isEmptyObject(obj: unknown): obj is object {
if (!isObject(obj)) {
return false;
}
@@ -140,27 +140,27 @@ export function isEmptyObject(obj: any): obj is any {
/**
* @returns whether the provided parameter is a JavaScript Function or not.
*/
export function isFunction(obj: any): obj is Function {
export function isFunction(obj: unknown): obj is Function {
return (typeof obj === 'function');
}
/**
* @returns whether the provided parameters is are JavaScript Function or not.
*/
export function areFunctions(...objects: any[]): boolean {
export function areFunctions(...objects: unknown[]): boolean {
return objects.length > 0 && objects.every(isFunction);
}
export type TypeConstraint = string | Function;
export function validateConstraints(args: any[], constraints: Array<TypeConstraint | undefined>): void {
export function validateConstraints(args: unknown[], constraints: Array<TypeConstraint | undefined>): void {
const len = Math.min(args.length, constraints.length);
for (let i = 0; i < len; i++) {
validateConstraint(args[i], constraints[i]);
}
}
export function validateConstraint(arg: any, constraint: TypeConstraint | undefined): void {
export function validateConstraint(arg: unknown, constraint: TypeConstraint | undefined): void {
if (isString(constraint)) {
if (typeof arg !== constraint) {
@@ -174,7 +174,7 @@ export function validateConstraint(arg: any, constraint: TypeConstraint | undefi
} catch {
// ignore
}
if (!isUndefinedOrNull(arg) && arg.constructor === constraint) {
if (!isUndefinedOrNull(arg) && (arg as any).constructor === constraint) {
return;
}
if (constraint.length === 1 && constraint.call(undefined, arg) === true) {
@@ -204,8 +204,8 @@ export function getAllMethodNames(obj: object): string[] {
return methods;
}
export function createProxyObject<T extends object>(methodNames: string[], invoke: (method: string, args: any[]) => any): T {
const createProxyMethod = (method: string): () => any => {
export function createProxyObject<T extends object>(methodNames: string[], invoke: (method: string, args: unknown[]) => unknown): T {
const createProxyMethod = (method: string): () => unknown => {
return function () {
const args = Array.prototype.slice.call(arguments, 0);
return invoke(method, args);
@@ -242,7 +242,7 @@ export type AddFirstParameterToFunctions<Target, TargetFunctionsReturnType, Firs
[K in keyof Target]:
// Function: add param to function
Target[K] extends (...args: any) => TargetFunctionsReturnType ? (firstArg: FirstParameter, ...args: Parameters<Target[K]>) => ReturnType<Target[K]> :
Target[K] extends (...args: any[]) => TargetFunctionsReturnType ? (firstArg: FirstParameter, ...args: Parameters<Target[K]>) => ReturnType<Target[K]> :
// Else: just leave as is
Target[K]

View File

@@ -19,13 +19,22 @@ for (let i = 0; i < 256; i++) {
// todo@jrieken
// 1. node nodejs use`crypto#randomBytes`, see: https://nodejs.org/docs/latest/api/crypto.html#crypto_crypto_randombytes_size_callback
// 2. use browser-crypto
const _fillRandomValues = function (bucket: Uint8Array): Uint8Array {
for (let i = 0; i < bucket.length; i++) {
bucket[i] = Math.floor(Math.random() * 256);
}
return bucket;
};
let _fillRandomValues: (bucket: Uint8Array) => Uint8Array;
declare const crypto: undefined | { getRandomValues(data: Uint8Array): Uint8Array };
if (typeof crypto === 'object' && typeof crypto.getRandomValues === 'function') {
// browser
_fillRandomValues = crypto.getRandomValues.bind(crypto);
} else {
_fillRandomValues = function (bucket: Uint8Array): Uint8Array {
for (let i = 0; i < bucket.length; i++) {
bucket[i] = Math.floor(Math.random() * 256);
}
return bucket;
};
}
export function generateUuid(): string {
// get data

View File

@@ -7,7 +7,6 @@ import * as fs from 'fs';
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';
import { promisify } from 'util';
/**
* Copied from: https://github.com/microsoft/vscode-node-debug/blob/master/src/node/pathUtilities.ts#L83
@@ -53,7 +52,7 @@ export function realcaseSync(path: string): string | null {
export async function realpath(path: string): Promise<string> {
try {
return await promisify(fs.realpath)(path);
return await fs.promises.realpath(path);
} catch (error) {
// We hit an error calling fs.realpath(). Since fs.realpath() is doing some path normalization
@@ -63,7 +62,7 @@ export async function realpath(path: string): Promise<string> {
// to not resolve links but to simply see if the path is read accessible or not.
const normalizedPath = normalizePath(path);
await promisify(fs.access)(normalizedPath, fs.constants.R_OK);
await fs.promises.access(normalizedPath, fs.constants.R_OK);
return normalizedPath;
}

View File

@@ -2,313 +2,258 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
/// <reference path="../../../typings/require.d.ts" />
//@ts-check
/**
* @param {NodeRequire} nodeRequire
* @param {typeof import('path')} path
* @param {typeof import('fs')} fs
* @param {typeof import('../common/performance')} perf
*/
function factory(nodeRequire, path, fs, perf) {
(function () {
'use strict';
/**
* @param {string} file
* @returns {Promise<boolean>}
* @param {NodeRequire} nodeRequire
* @param {typeof import('path')} path
* @param {typeof import('fs')} fs
* @param {typeof import('../common/performance')} perf
*/
function exists(file) {
return new Promise(c => fs.exists(file, c));
}
function factory(nodeRequire, path, fs, perf) {
/**
* @param {string} file
* @returns {Promise<void>}
*/
function touch(file) {
return new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });
}
/**
* @param {string} file
* @returns {Promise<object>}
*/
function lstat(file) {
return new Promise((c, e) => fs.lstat(file, (err, stats) => err ? e(err) : c(stats)));
}
/**
* @param {string} dir
* @returns {Promise<string[]>}
*/
function readdir(dir) {
return new Promise((c, e) => fs.readdir(dir, (err, files) => err ? e(err) : c(files)));
}
/**
* @param {string} dir
* @returns {Promise<string>}
*/
function mkdirp(dir) {
return new Promise((c, e) => fs.mkdir(dir, { recursive: true }, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir)));
}
/**
* @param {string} dir
* @returns {Promise<void>}
*/
function rmdir(dir) {
return new Promise((c, e) => fs.rmdir(dir, err => err ? e(err) : c(undefined)));
}
/**
* @param {string} file
* @returns {Promise<void>}
*/
function unlink(file) {
return new Promise((c, e) => fs.unlink(file, err => err ? e(err) : c(undefined)));
}
/**
* @param {string} location
* @returns {Promise<void>}
*/
function rimraf(location) {
return lstat(location).then(stat => {
if (stat.isDirectory() && !stat.isSymbolicLink()) {
return readdir(location)
.then(children => Promise.all(children.map(child => rimraf(path.join(location, child)))))
.then(() => rmdir(location));
} else {
return unlink(location);
}
}, err => {
if (err.code === 'ENOENT') {
return undefined;
}
throw err;
});
}
function readFile(file) {
return new Promise(function (resolve, reject) {
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
/**
* @param {string} file
* @param {string} content
* @returns {Promise<void>}
*/
function writeFile(file, content) {
return new Promise(function (resolve, reject) {
fs.writeFile(file, content, 'utf8', function (err) {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
/**
* @param {string} userDataPath
* @returns {object}
*/
function getLanguagePackConfigurations(userDataPath) {
const configFile = path.join(userDataPath, 'languagepacks.json');
try {
return nodeRequire(configFile);
} catch (err) {
// Do nothing. If we can't read the file we have no
// language pack config.
/**
* @param {string} file
* @returns {Promise<boolean>}
*/
function exists(file) {
return new Promise(c => fs.exists(file, c));
}
return undefined;
}
/**
* @param {object} config
* @param {string} locale
*/
function resolveLanguagePackLocale(config, locale) {
try {
while (locale) {
if (config[locale]) {
return locale;
} else {
const index = locale.lastIndexOf('-');
if (index > 0) {
locale = locale.substring(0, index);
/**
* @param {string} file
* @returns {Promise<void>}
*/
function touch(file) {
return new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });
}
/**
* @param {string} dir
* @returns {Promise<string>}
*/
function mkdirp(dir) {
return new Promise((c, e) => fs.mkdir(dir, { recursive: true }, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir)));
}
/**
* @param {string} location
* @returns {Promise<void>}
*/
function rimraf(location) {
return new Promise((c, e) => fs.rmdir(location, { recursive: true }, err => (err && err.code !== 'ENOENT') ? e(err) : c()));
}
/**
* @param {string} file
* @returns {Promise<string>}
*/
function readFile(file) {
return new Promise((c, e) => fs.readFile(file, 'utf8', (err, data) => err ? e(err) : c(data)));
}
/**
* @param {string} file
* @param {string} content
* @returns {Promise<void>}
*/
function writeFile(file, content) {
return new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
}
/**
* @param {string} userDataPath
* @returns {object}
*/
function getLanguagePackConfigurations(userDataPath) {
const configFile = path.join(userDataPath, 'languagepacks.json');
try {
return nodeRequire(configFile);
} catch (err) {
// Do nothing. If we can't read the file we have no
// language pack config.
}
return undefined;
}
/**
* @param {object} config
* @param {string} locale
*/
function resolveLanguagePackLocale(config, locale) {
try {
while (locale) {
if (config[locale]) {
return locale;
} else {
return undefined;
const index = locale.lastIndexOf('-');
if (index > 0) {
locale = locale.substring(0, index);
} else {
return undefined;
}
}
}
} catch (err) {
console.error('Resolving language pack configuration failed.', err);
}
} catch (err) {
console.error('Resolving language pack configuration failed.', err);
}
return undefined;
}
/**
* @param {string} commit
* @param {string} userDataPath
* @param {string} metaDataFile
* @param {string} locale
*/
function getNLSConfiguration(commit, userDataPath, metaDataFile, locale) {
if (locale === 'pseudo') {
return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true });
return undefined;
}
if (process.env['VSCODE_DEV']) {
return Promise.resolve({ locale: locale, availableLanguages: {} });
}
// We have a built version so we have extracted nls file. Try to find
// the right file to use.
// Check if we have an English or English US locale. If so fall to default since that is our
// English translation (we don't ship *.nls.en.json files)
if (locale && (locale === 'en' || locale === 'en-us')) {
return Promise.resolve({ locale: locale, availableLanguages: {} });
}
const initialLocale = locale;
perf.mark('code/willGenerateNls');
const defaultResult = function (locale) {
perf.mark('code/didGenerateNls');
return Promise.resolve({ locale: locale, availableLanguages: {} });
};
try {
if (!commit) {
return defaultResult(initialLocale);
/**
* @param {string} commit
* @param {string} userDataPath
* @param {string} metaDataFile
* @param {string} locale
*/
function getNLSConfiguration(commit, userDataPath, metaDataFile, locale) {
if (locale === 'pseudo') {
return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true });
}
const configs = getLanguagePackConfigurations(userDataPath);
if (!configs) {
return defaultResult(initialLocale);
if (process.env['VSCODE_DEV']) {
return Promise.resolve({ locale: locale, availableLanguages: {} });
}
locale = resolveLanguagePackLocale(configs, locale);
if (!locale) {
return defaultResult(initialLocale);
// We have a built version so we have extracted nls file. Try to find
// the right file to use.
// Check if we have an English or English US locale. If so fall to default since that is our
// English translation (we don't ship *.nls.en.json files)
if (locale && (locale === 'en' || locale === 'en-us')) {
return Promise.resolve({ locale: locale, availableLanguages: {} });
}
const packConfig = configs[locale];
let mainPack;
if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') {
return defaultResult(initialLocale);
}
return exists(mainPack).then(fileExists => {
if (!fileExists) {
const initialLocale = locale;
perf.mark('code/willGenerateNls');
const defaultResult = function (locale) {
perf.mark('code/didGenerateNls');
return Promise.resolve({ locale: locale, availableLanguages: {} });
};
try {
if (!commit) {
return defaultResult(initialLocale);
}
const packId = packConfig.hash + '.' + locale;
const cacheRoot = path.join(userDataPath, 'clp', packId);
const coreLocation = path.join(cacheRoot, commit);
const translationsConfigFile = path.join(cacheRoot, 'tcf.json');
const corruptedFile = path.join(cacheRoot, 'corrupted.info');
const result = {
locale: initialLocale,
availableLanguages: { '*': locale },
_languagePackId: packId,
_translationsConfigFile: translationsConfigFile,
_cacheRoot: cacheRoot,
_resolvedLanguagePackCoreLocation: coreLocation,
_corruptedFile: corruptedFile
};
return exists(corruptedFile).then(corrupted => {
// The nls cache directory is corrupted.
let toDelete;
if (corrupted) {
toDelete = rimraf(cacheRoot);
} else {
toDelete = Promise.resolve(undefined);
const configs = getLanguagePackConfigurations(userDataPath);
if (!configs) {
return defaultResult(initialLocale);
}
locale = resolveLanguagePackLocale(configs, locale);
if (!locale) {
return defaultResult(initialLocale);
}
const packConfig = configs[locale];
let mainPack;
if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') {
return defaultResult(initialLocale);
}
return exists(mainPack).then(fileExists => {
if (!fileExists) {
return defaultResult(initialLocale);
}
return toDelete.then(() => {
return exists(coreLocation).then(fileExists => {
if (fileExists) {
// We don't wait for this. No big harm if we can't touch
touch(coreLocation).catch(() => { });
perf.mark('code/didGenerateNls');
return result;
}
return mkdirp(coreLocation).then(() => {
return Promise.all([readFile(metaDataFile), readFile(mainPack)]);
}).then(values => {
const metadata = JSON.parse(values[0]);
const packData = JSON.parse(values[1]).contents;
const bundles = Object.keys(metadata.bundles);
const writes = [];
for (const bundle of bundles) {
const modules = metadata.bundles[bundle];
const target = Object.create(null);
for (const module of modules) {
const keys = metadata.keys[module];
const defaultMessages = metadata.messages[module];
const translations = packData[module];
let targetStrings;
if (translations) {
targetStrings = [];
for (let i = 0; i < keys.length; i++) {
const elem = keys[i];
const key = typeof elem === 'string' ? elem : elem.key;
let translatedMessage = translations[key];
if (translatedMessage === undefined) {
translatedMessage = defaultMessages[i];
}
targetStrings.push(translatedMessage);
}
} else {
targetStrings = defaultMessages;
}
target[module] = targetStrings;
}
writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
const packId = packConfig.hash + '.' + locale;
const cacheRoot = path.join(userDataPath, 'clp', packId);
const coreLocation = path.join(cacheRoot, commit);
const translationsConfigFile = path.join(cacheRoot, 'tcf.json');
const corruptedFile = path.join(cacheRoot, 'corrupted.info');
const result = {
locale: initialLocale,
availableLanguages: { '*': locale },
_languagePackId: packId,
_translationsConfigFile: translationsConfigFile,
_cacheRoot: cacheRoot,
_resolvedLanguagePackCoreLocation: coreLocation,
_corruptedFile: corruptedFile
};
return exists(corruptedFile).then(corrupted => {
// The nls cache directory is corrupted.
let toDelete;
if (corrupted) {
toDelete = rimraf(cacheRoot);
} else {
toDelete = Promise.resolve(undefined);
}
return toDelete.then(() => {
return exists(coreLocation).then(fileExists => {
if (fileExists) {
// We don't wait for this. No big harm if we can't touch
touch(coreLocation).catch(() => { });
perf.mark('code/didGenerateNls');
return result;
}
writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
return Promise.all(writes);
}).then(() => {
perf.mark('code/didGenerateNls');
return result;
}).catch(err => {
console.error('Generating translation files failed.', err);
return defaultResult(locale);
return mkdirp(coreLocation).then(() => {
return Promise.all([readFile(metaDataFile), readFile(mainPack)]);
}).then(values => {
const metadata = JSON.parse(values[0]);
const packData = JSON.parse(values[1]).contents;
const bundles = Object.keys(metadata.bundles);
const writes = [];
for (const bundle of bundles) {
const modules = metadata.bundles[bundle];
const target = Object.create(null);
for (const module of modules) {
const keys = metadata.keys[module];
const defaultMessages = metadata.messages[module];
const translations = packData[module];
let targetStrings;
if (translations) {
targetStrings = [];
for (let i = 0; i < keys.length; i++) {
const elem = keys[i];
const key = typeof elem === 'string' ? elem : elem.key;
let translatedMessage = translations[key];
if (translatedMessage === undefined) {
translatedMessage = defaultMessages[i];
}
targetStrings.push(translatedMessage);
}
} else {
targetStrings = defaultMessages;
}
target[module] = targetStrings;
}
writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
}
writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
return Promise.all(writes);
}).then(() => {
perf.mark('code/didGenerateNls');
return result;
}).catch(err => {
console.error('Generating translation files failed.', err);
return defaultResult(locale);
});
});
});
});
});
});
} catch (err) {
console.error('Generating translation files failed.', err);
return defaultResult(locale);
} catch (err) {
console.error('Generating translation files failed.', err);
return defaultResult(locale);
}
}
return {
getNLSConfiguration
};
}
return {
getNLSConfiguration
};
}
if (typeof define === 'function') {
// amd
define(['path', 'fs', 'vs/base/common/performance'], function (path, fs, perf) { return factory(require.__$__nodeRequire, path, fs, perf); });
} else if (typeof module === 'object' && typeof module.exports === 'object') {
const path = require('path');
const fs = require('fs');
const perf = require('../common/performance');
module.exports = factory(require, path, fs, perf);
} else {
throw new Error('Unknown context');
}
if (typeof define === 'function') {
// amd
define(['require', 'path', 'fs', 'vs/base/common/performance'], function (require, /** @type {typeof import('path')} */ path, /** @type {typeof import('fs')} */ fs, /** @type {typeof import('../common/performance')} */ perf) { return factory(require.__$__nodeRequire, path, fs, perf); });
} else if (typeof module === 'object' && typeof module.exports === 'object') {
const path = require('path');
const fs = require('fs');
const perf = require('../common/performance');
module.exports = factory(require, path, fs, perf);
} else {
throw new Error('Unknown context');
}
}());

View File

@@ -7,13 +7,14 @@ import * as fs from 'fs';
import { tmpdir } from 'os';
import { join } from 'vs/base/common/path';
import { Queue } from 'vs/base/common/async';
import { isMacintosh, isWindows } from 'vs/base/common/platform';
import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { Event } from 'vs/base/common/event';
import { promisify } from 'util';
import { isRootOrDriveLetter } from 'vs/base/common/extpath';
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
@@ -25,6 +26,10 @@ 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
//#region rimraf
export enum RimRafMode {
/**
@@ -40,12 +45,19 @@ export enum RimRafMode {
MOVE
}
/**
* Allows to delete the provied path (either file or folder) recursively
* with the options:
* - `UNLINK`: direct removal from disk
* - `MOVE`: faster variant that first moves the target to temp dir and then
* deletes it in the background without waiting for that to finish.
*/
export async function rimraf(path: string, mode = RimRafMode.UNLINK): Promise<void> {
if (isRootOrDriveLetter(path)) {
throw new Error('rimraf - will refuse to recursively delete root');
}
// delete: via unlink
// delete: via rmDir
if (mode === RimRafMode.UNLINK) {
return rimrafUnlink(path);
}
@@ -54,32 +66,17 @@ export async function rimraf(path: string, mode = RimRafMode.UNLINK): Promise<vo
return rimrafMove(path);
}
async function rimrafUnlink(path: string): Promise<void> {
async function rimrafMove(path: string): Promise<void> {
try {
const stat = await lstat(path);
// Folder delete (recursive) - NOT for symbolic links though!
if (stat.isDirectory() && !stat.isSymbolicLink()) {
// Children
const children = await readdir(path);
await Promise.all(children.map(child => rimrafUnlink(join(path, child))));
// Folder
await promisify(fs.rmdir)(path);
const pathInTemp = join(tmpdir(), generateUuid());
try {
await fs.promises.rename(path, pathInTemp);
} catch (error) {
return rimrafUnlink(path); // if rename fails, delete without tmp dir
}
// Single file delete
else {
// chmod as needed to allow for unlink
const mode = stat.mode;
if (!(mode & fs.constants.S_IWUSR)) {
await chmod(path, mode | fs.constants.S_IWUSR);
}
return unlink(path);
}
// Delete but do not return as promise
rimrafUnlink(pathInTemp).catch(error => {/* ignore */ });
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
@@ -87,22 +84,8 @@ async function rimrafUnlink(path: string): Promise<void> {
}
}
async function rimrafMove(path: string): Promise<void> {
try {
const pathInTemp = join(tmpdir(), generateUuid());
try {
await rename(path, pathInTemp);
} catch (error) {
return rimrafUnlink(path); // if rename fails, delete without tmp dir
}
// Delete but do not return as promise
rimrafUnlink(pathInTemp);
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}
async function rimrafUnlink(path: string): Promise<void> {
return fs.promises.rmdir(path, { recursive: true, maxRetries: 3 });
}
export function rimrafSync(path: string): void {
@@ -110,193 +93,281 @@ export function rimrafSync(path: string): void {
throw new Error('rimraf - will refuse to recursively delete root');
}
fs.rmdirSync(path, { recursive: true });
}
//#endregion
//#region readdir with NFC support (macos)
export interface IDirent {
name: string;
isFile(): boolean;
isDirectory(): boolean;
isSymbolicLink(): boolean;
}
/**
* Drop-in replacement of `fs.readdir` with support
* for converting from macOS NFD unicon form to NFC
* (https://github.com/nodejs/node/issues/2165)
*/
export async function readdir(path: string): Promise<string[]>;
export async function readdir(path: string, options: { withFileTypes: true }): Promise<IDirent[]>;
export async function readdir(path: string, options?: { withFileTypes: true }): Promise<(string | IDirent)[]> {
return handleDirectoryChildren(await (options ? safeReaddirWithFileTypes(path) : fs.promises.readdir(path)));
}
async function safeReaddirWithFileTypes(path: string): Promise<IDirent[]> {
try {
const stat = fs.lstatSync(path);
// Folder delete (recursive) - NOT for symbolic links though!
if (stat.isDirectory() && !stat.isSymbolicLink()) {
// Children
const children = readdirSync(path);
children.map(child => rimrafSync(join(path, child)));
// Folder
fs.rmdirSync(path);
}
// Single file delete
else {
// chmod as needed to allow for unlink
const mode = stat.mode;
if (!(mode & fs.constants.S_IWUSR)) {
fs.chmodSync(path, mode | fs.constants.S_IWUSR);
}
return fs.unlinkSync(path);
}
return await fs.promises.readdir(path, { withFileTypes: true });
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}
}
export async function readdir(path: string): Promise<string[]> {
return handleDirectoryChildren(await promisify(fs.readdir)(path));
}
export async function readdirWithFileTypes(path: string): Promise<fs.Dirent[]> {
const children = await promisify(fs.readdir)(path, { withFileTypes: true });
// Mac: uses NFD unicode form on disk, but we want NFC
// See also https://github.com/nodejs/node/issues/2165
if (isMacintosh) {
for (const child of children) {
child.name = normalizeNFC(child.name);
}
console.warn('[node.js fs] readdir with filetypes failed with error: ', error);
}
return children;
// Fallback to manually reading and resolving each
// children of the folder in case we hit an error
// previously.
// This can only really happen on exotic file systems
// such as explained in #115645 where we get entries
// from `readdir` that we can later not `lstat`.
const result: IDirent[] = [];
const children = await readdir(path);
for (const child of children) {
let isFile = false;
let isDirectory = false;
let isSymbolicLink = false;
try {
const lstat = await fs.promises.lstat(join(path, child));
isFile = lstat.isFile();
isDirectory = lstat.isDirectory();
isSymbolicLink = lstat.isSymbolicLink();
} catch (error) {
console.warn('[node.js fs] unexpected error from lstat after readdir: ', error);
}
result.push({
name: child,
isFile: () => isFile,
isDirectory: () => isDirectory,
isSymbolicLink: () => isSymbolicLink
});
}
return result;
}
/**
* Drop-in replacement of `fs.readdirSync` with support
* for converting from macOS NFD unicon form to NFC
* (https://github.com/nodejs/node/issues/2165)
*/
export function readdirSync(path: string): string[] {
return handleDirectoryChildren(fs.readdirSync(path));
}
function handleDirectoryChildren(children: string[]): string[] {
// Mac: uses NFD unicode form on disk, but we want NFC
// See also https://github.com/nodejs/node/issues/2165
if (isMacintosh) {
return children.map(child => normalizeNFC(child));
}
function handleDirectoryChildren(children: string[]): string[];
function handleDirectoryChildren(children: IDirent[]): IDirent[];
function handleDirectoryChildren(children: (string | IDirent)[]): (string | IDirent)[];
function handleDirectoryChildren(children: (string | IDirent)[]): (string | IDirent)[] {
return children.map(child => {
return children;
}
// Mac: uses NFD unicode form on disk, but we want NFC
// See also https://github.com/nodejs/node/issues/2165
export function exists(path: string): Promise<boolean> {
return promisify(fs.exists)(path);
}
export function chmod(path: string, mode: number): Promise<void> {
return promisify(fs.chmod)(path, mode);
}
export function stat(path: string): Promise<fs.Stats> {
return promisify(fs.stat)(path);
}
export interface IStatAndLink {
// The stats of the file. If the file is a symbolic
// link, the stats will be of that target file and
// not the link itself.
// If the file is a symbolic link pointing to a non
// existing file, the stat will be of the link and
// the `dangling` flag will indicate this.
stat: fs.Stats;
// Will be provided if the resource is a symbolic link
// on disk. Use the `dangling` flag to find out if it
// points to a resource that does not exist on disk.
symbolicLink?: { dangling: boolean };
}
export async function statLink(path: string): Promise<IStatAndLink> {
// First stat the link
let lstats: fs.Stats | undefined;
try {
lstats = await lstat(path);
// Return early if the stat is not a symbolic link at all
if (!lstats.isSymbolicLink()) {
return { stat: lstats };
}
} catch (error) {
/* ignore - use stat() instead */
}
// If the stat is a symbolic link or failed to stat, use fs.stat()
// which for symbolic links will stat the target they point to
try {
const stats = await stat(path);
return { stat: stats, symbolicLink: lstats?.isSymbolicLink() ? { dangling: false } : undefined };
} catch (error) {
// If the link points to a non-existing file we still want
// to return it as result while setting dangling: true flag
if (error.code === 'ENOENT' && lstats) {
return { stat: lstats, symbolicLink: { dangling: true } };
if (typeof child === 'string') {
return isMacintosh ? normalizeNFC(child) : child;
}
// Windows: workaround a node.js bug where reparse points
// are not supported (https://github.com/nodejs/node/issues/36790)
if (isWindows && error.code === 'EACCES' && lstats) {
try {
const stats = await stat(await readlink(path));
child.name = isMacintosh ? normalizeNFC(child.name) : child.name;
return { stat: stats, symbolicLink: lstats.isSymbolicLink() ? { dangling: false } : undefined };
} catch (error) {
return child;
});
}
// If the link points to a non-existing file we still want
// to return it as result while setting dangling: true flag
if (error.code === 'ENOENT') {
return { stat: lstats, symbolicLink: { dangling: true } };
}
/**
* A convinience method to read all children of a path that
* are directories.
*/
export async function readDirsInDir(dirPath: string): Promise<string[]> {
const children = await readdir(dirPath);
const directories: string[] = [];
throw error;
for (const child of children) {
if (await SymlinkSupport.existsDirectory(join(dirPath, child))) {
directories.push(child);
}
}
return directories;
}
//#endregion
//#region whenDeleted()
/**
* A `Promise` that resolves when the provided `path`
* is deleted from disk.
*/
export function whenDeleted(path: string, intervalMs = 1000): Promise<void> {
return new Promise<void>(resolve => {
let running = false;
const interval = setInterval(() => {
if (!running) {
running = true;
fs.access(path, err => {
running = false;
if (err) {
clearInterval(interval);
resolve(undefined);
}
});
}
}, intervalMs);
});
}
//#endregion
//#region Methods with symbolic links support
export namespace SymlinkSupport {
export interface IStats {
// The stats of the file. If the file is a symbolic
// link, the stats will be of that target file and
// not the link itself.
// If the file is a symbolic link pointing to a non
// existing file, the stat will be of the link and
// the `dangling` flag will indicate this.
stat: fs.Stats;
// Will be provided if the resource is a symbolic link
// on disk. Use the `dangling` flag to find out if it
// points to a resource that does not exist on disk.
symbolicLink?: { dangling: boolean };
}
/**
* Resolves the `fs.Stats` of the provided path. If the path is a
* symbolic link, the `fs.Stats` will be from the target it points
* to. If the target does not exist, `dangling: true` will be returned
* as `symbolicLink` value.
*/
export async function stat(path: string): Promise<IStats> {
// First stat the link
let lstats: fs.Stats | undefined;
try {
lstats = await fs.promises.lstat(path);
// Return early if the stat is not a symbolic link at all
if (!lstats.isSymbolicLink()) {
return { stat: lstats };
}
} catch (error) {
/* ignore - use stat() instead */
}
throw error;
// If the stat is a symbolic link or failed to stat, use fs.stat()
// which for symbolic links will stat the target they point to
try {
const stats = await fs.promises.stat(path);
return { stat: stats, symbolicLink: lstats?.isSymbolicLink() ? { dangling: false } : undefined };
} catch (error) {
// If the link points to a non-existing file we still want
// to return it as result while setting dangling: true flag
if (error.code === 'ENOENT' && lstats) {
return { stat: lstats, symbolicLink: { dangling: true } };
}
// Windows: workaround a node.js bug where reparse points
// are not supported (https://github.com/nodejs/node/issues/36790)
if (isWindows && error.code === 'EACCES') {
try {
const stats = await fs.promises.stat(await fs.promises.readlink(path));
return { stat: stats, symbolicLink: { dangling: false } };
} catch (error) {
// If the link points to a non-existing file we still want
// to return it as result while setting dangling: true flag
if (error.code === 'ENOENT' && lstats) {
return { stat: lstats, symbolicLink: { dangling: true } };
}
throw error;
}
}
throw error;
}
}
/**
* Figures out if the `path` exists and is a file with support
* for symlinks.
*
* Note: this will return `false` for a symlink that exists on
* disk but is dangling (pointing to a non-existing path).
*
* Use `exists` if you only care about the path existing on disk
* or not without support for symbolic links.
*/
export async function existsFile(path: string): Promise<boolean> {
try {
const { stat, symbolicLink } = await SymlinkSupport.stat(path);
return stat.isFile() && symbolicLink?.dangling !== true;
} catch (error) {
// Ignore, path might not exist
}
return false;
}
/**
* Figures out if the `path` exists and is a directory with support for
* symlinks.
*
* Note: this will return `false` for a symlink that exists on
* disk but is dangling (pointing to a non-existing path).
*
* Use `exists` if you only care about the path existing on disk
* or not without support for symbolic links.
*/
export async function existsDirectory(path: string): Promise<boolean> {
try {
const { stat, symbolicLink } = await SymlinkSupport.stat(path);
return stat.isDirectory() && symbolicLink?.dangling !== true;
} catch (error) {
// Ignore, path might not exist
}
return false;
}
}
export function lstat(path: string): Promise<fs.Stats> {
return promisify(fs.lstat)(path);
}
//#endregion
export function rename(oldPath: string, newPath: string): Promise<void> {
return promisify(fs.rename)(oldPath, newPath);
}
export function renameIgnoreError(oldPath: string, newPath: string): Promise<void> {
return new Promise(resolve => fs.rename(oldPath, newPath, () => resolve()));
}
export function readlink(path: string): Promise<string> {
return promisify(fs.readlink)(path);
}
export function unlink(path: string): Promise<void> {
return promisify(fs.unlink)(path);
}
export function symlink(target: string, path: string, type?: string): Promise<void> {
return promisify(fs.symlink)(target, path, type);
}
export function truncate(path: string, len: number): Promise<void> {
return promisify(fs.truncate)(path, len);
}
export function readFile(path: string): Promise<Buffer>;
export function readFile(path: string, encoding: string): Promise<string>;
export function readFile(path: string, encoding?: string): Promise<Buffer | string> {
return promisify(fs.readFile)(path, encoding);
}
export async function mkdirp(path: string, mode?: number): Promise<void> {
return promisify(fs.mkdir)(path, { mode, recursive: true });
}
// 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();
//#region Write File
/**
* Same as `fs.writeFile` but with an additional call to
* `fs.fdatasync` after writing to ensure changes are
* flushed to disk.
*
* In addition, multiple writes to the same path are queued.
*/
export function writeFile(path: string, data: string, options?: IWriteFileOptions): Promise<void>;
export function writeFile(path: string, data: Buffer, options?: IWriteFileOptions): Promise<void>;
export function writeFile(path: string, data: Uint8Array, options?: IWriteFileOptions): Promise<void>;
@@ -311,6 +382,11 @@ export function writeFile(path: string, data: string | Buffer | Uint8Array, opti
});
}
// 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) {
@@ -388,6 +464,11 @@ function doWriteFileAndFlush(path: string, data: string | Buffer | Uint8Array, o
});
}
/**
* Same as `fs.writeFileSync` but with an additional call to
* `fs.fdatasyncSync` after writing to ensure changes are
* flushed to disk.
*/
export function writeFileSync(path: string, data: string | Buffer, options?: IWriteFileOptions): void {
const ensuredOptions = ensureWriteOptions(options);
@@ -426,87 +507,48 @@ function ensureWriteOptions(options?: IWriteFileOptions): IEnsuredWriteFileOptio
};
}
export async function readDirsInDir(dirPath: string): Promise<string[]> {
const children = await readdir(dirPath);
const directories: string[] = [];
//#endregion
for (const child of children) {
if (await dirExists(join(dirPath, child))) {
directories.push(child);
}
}
return directories;
}
export async function dirExists(path: string): Promise<boolean> {
try {
const { stat, symbolicLink } = await statLink(path);
return stat.isDirectory() && symbolicLink?.dangling !== true;
} catch (error) {
// Ignore, path might not exist
}
return false;
}
export async function fileExists(path: string): Promise<boolean> {
try {
const { stat, symbolicLink } = await statLink(path);
return stat.isFile() && symbolicLink?.dangling !== true;
} catch (error) {
// Ignore, path might not exist
}
return false;
}
export function whenDeleted(path: string): Promise<void> {
// Complete when wait marker file is deleted
return new Promise<void>(resolve => {
let running = false;
const interval = setInterval(() => {
if (!running) {
running = true;
fs.exists(path, exists => {
running = false;
if (!exists) {
clearInterval(interval);
resolve(undefined);
}
});
}
}, 1000);
});
}
//#region Move / Copy
/**
* A drop-in replacement for `fs.rename` that:
* - updates the `mtime` of the `source` after the operation
* - allows to move across multiple disks
*/
export async function move(source: string, target: string): Promise<void> {
if (source === target) {
return;
return; // simulate node.js behaviour here and do a no-op if paths match
}
// We have been updating `mtime` for move operations for files since the
// beginning for reasons that are no longer quite clear, but changing
// this could be risky as well. As such, trying to reason about it:
// It is very common as developer to have file watchers enabled that watch
// the current workspace for changes. Updating the `mtime` might make it
// easier for these watchers to recognize an actual change. Since changing
// a source code file also updates the `mtime`, moving a file should do so
// as well because conceptually it is a change of a similar category.
async function updateMtime(path: string): Promise<void> {
const stat = await lstat(path);
if (stat.isDirectory() || stat.isSymbolicLink()) {
return; // only for files
}
const fd = await promisify(fs.open)(path, 'a');
try {
await promisify(fs.futimes)(fd, stat.atime, new Date());
} catch (error) {
//ignore
}
const stat = await fs.promises.lstat(path);
if (stat.isDirectory() || stat.isSymbolicLink()) {
return; // only for files
}
return promisify(fs.close)(fd);
const fh = await fs.promises.open(path, 'a');
try {
await fh.utimes(stat.atime, new Date());
} finally {
await fh.close();
}
} catch (error) {
// Ignore any error
}
}
try {
await rename(source, target);
await fs.promises.rename(source, target);
await updateMtime(target);
} catch (error) {
@@ -519,7 +561,7 @@ export async function move(source: string, target: string): Promise<void> {
// 2.) The user tries to rename a file/folder that ends with a dot. This is not
// really possible to move then, at least on UNC devices.
if (source.toLowerCase() !== target.toLowerCase() && error.code === 'EXDEV' || source.endsWith('.')) {
await copy(source, target);
await copy(source, target, { preserveSymlinks: false /* copying to another device */ });
await rimraf(source, RimRafMode.MOVE);
await updateMtime(target);
} else {
@@ -528,74 +570,119 @@ export async function move(source: string, target: string): Promise<void> {
}
}
interface ICopyPayload {
readonly root: { source: string, target: string };
readonly options: { preserveSymlinks: boolean };
readonly handledSourcePaths: Set<string>;
}
/**
* Recursively copies all of `source` to `target`.
*
* The options `preserveSymlinks` configures how symbolic
* links should be handled when encountered. Set to
* `false` to not preserve them and `true` otherwise.
*/
export async function copy(source: string, target: string, options: { preserveSymlinks: boolean }): Promise<void> {
return doCopy(source, target, { root: { source, target }, options, handledSourcePaths: new Set<string>() });
}
// When copying a file or folder, we want to preserve the mode
// it had and as such provide it when creating. However, modes
// can go beyond what we expect (see link below), so we mask it.
// (https://github.com/nodejs/node-v0.x-archive/issues/3045#issuecomment-4862588)
//
// The `copy` method is very old so we should probably revisit
// it's implementation and check wether this mask is still needed.
const COPY_MODE_MASK = 0o777;
export async function copy(source: string, target: string, handledSourcesIn?: { [path: string]: boolean }): Promise<void> {
async function doCopy(source: string, target: string, payload: ICopyPayload): Promise<void> {
// Keep track of paths already copied to prevent
// cycles from symbolic links to cause issues
const handledSources = handledSourcesIn ?? Object.create(null);
if (handledSources[source]) {
if (payload.handledSourcePaths.has(source)) {
return;
} else {
handledSources[source] = true;
payload.handledSourcePaths.add(source);
}
const { stat, symbolicLink } = await statLink(source);
if (symbolicLink?.dangling) {
return; // skip over dangling symbolic links (https://github.com/microsoft/vscode/issues/111621)
const { stat, symbolicLink } = await SymlinkSupport.stat(source);
// 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) {
try {
return await doCopySymlink(source, target, payload);
} catch (error) {
// in any case of an error fallback to normal copy via dereferencing
console.warn('[node.js fs] copy of symlink failed: ', error);
}
}
}
if (!stat.isDirectory()) {
// Folder
if (stat.isDirectory()) {
return doCopyDirectory(source, target, stat.mode & COPY_MODE_MASK, payload);
}
// File or file-like
else {
return doCopyFile(source, target, stat.mode & COPY_MODE_MASK);
}
}
async function doCopyDirectory(source: string, target: string, mode: number, payload: ICopyPayload): Promise<void> {
// Create folder
await mkdirp(target, stat.mode & COPY_MODE_MASK);
await fs.promises.mkdir(target, { recursive: true, mode });
// Copy each file recursively
const files = await readdir(source);
for (let i = 0; i < files.length; i++) {
const file = files[i];
await copy(join(source, file), join(target, file), handledSources);
for (const file of files) {
await doCopy(join(source, file), join(target, file), payload);
}
}
async function doCopyFile(source: string, target: string, mode: number): Promise<void> {
return new Promise((resolve, reject) => {
const reader = fs.createReadStream(source);
const writer = fs.createWriteStream(target, { mode });
let finished = false;
const finish = (error?: Error) => {
if (!finished) {
finished = true;
// Copy file
await fs.promises.copyFile(source, target);
// in error cases, pass to callback
if (error) {
return reject(error);
}
// we need to explicitly chmod because of https://github.com/nodejs/node/issues/1104
fs.chmod(target, mode, error => error ? reject(error) : resolve());
}
};
// handle errors properly
reader.once('error', error => finish(error));
writer.once('error', error => finish(error));
// we are done (underlying fd has been closed)
writer.once('close', () => finish());
// start piping
reader.pipe(writer);
});
// restore mode (https://github.com/nodejs/node/issues/1104)
await fs.promises.chmod(target, mode);
}
async function doCopySymlink(source: string, target: string, payload: ICopyPayload): Promise<void> {
// Figure out link target
let linkTarget = await fs.promises.readlink(source);
// Special case: the symlink points to a target that is
// actually within the path that is being copied. In that
// case we want the symlink to point to the target and
// not the source
if (isEqualOrParent(linkTarget, payload.root.source, !isLinux)) {
linkTarget = join(payload.root.target, linkTarget.substr(payload.root.source.length + 1));
}
// Create symlink
await fs.promises.symlink(linkTarget, target);
}
//#endregion
//#region Async FS Methods
export async function exists(path: string): Promise<boolean> {
try {
await fs.promises.access(path);
return true;
} catch {
return false;
}
}
//#endregion

View File

@@ -8,18 +8,72 @@ import * as os from 'os';
import * as path from 'vs/base/common/path';
import { env } from 'vs/base/common/process';
const WindowsPowerShell64BitLabel = 'Windows PowerShell';
const WindowsPowerShell32BitLabel = 'Windows PowerShell (x86)';
// This is required, since parseInt("7-preview") will return 7.
const IntRegex: RegExp = /^\d+$/;
const PwshMsixRegex: RegExp = /^Microsoft.PowerShell_.*/;
const PwshPreviewMsixRegex: RegExp = /^Microsoft.PowerShellPreview_.*/;
// The platform details descriptor for the platform we're on
const isProcess64Bit: boolean = process.arch === 'x64';
const isOS64Bit: boolean = isProcess64Bit || os.arch() === 'x64';
const enum Arch {
x64,
x86,
ARM
}
let processArch: Arch;
switch (process.arch) {
case 'ia32':
case 'x32':
processArch = Arch.x86;
break;
case 'arm':
case 'arm64':
processArch = Arch.ARM;
break;
default:
processArch = Arch.x64;
break;
}
/*
Currently, here are the values for these environment variables on their respective archs:
On x86 process on x86:
PROCESSOR_ARCHITECTURE is X86
PROCESSOR_ARCHITEW6432 is undefined
On x86 process on x64:
PROCESSOR_ARCHITECTURE is X86
PROCESSOR_ARCHITEW6432 is AMD64
On x64 process on x64:
PROCESSOR_ARCHITECTURE is AMD64
PROCESSOR_ARCHITEW6432 is undefined
On ARM process on ARM:
PROCESSOR_ARCHITECTURE is ARM64
PROCESSOR_ARCHITEW6432 is undefined
On x86 process on ARM:
PROCESSOR_ARCHITECTURE is X86
PROCESSOR_ARCHITEW6432 is ARM64
On x64 process on ARM:
PROCESSOR_ARCHITECTURE is ARM64
PROCESSOR_ARCHITEW6432 is undefined
*/
let osArch: Arch;
if (process.env['PROCESSOR_ARCHITEW6432']) {
osArch = process.env['PROCESSOR_ARCHITEW6432'] === 'ARM64'
? Arch.ARM
: Arch.x64;
} else if (process.env['PROCESSOR_ARCHITECTURE'] === 'ARM64') {
osArch = Arch.ARM;
} else if (process.env['PROCESSOR_ARCHITECTURE'] === 'X86') {
osArch = Arch.x86;
} else {
osArch = Arch.x64;
}
export interface IPowerShellExeDetails {
readonly displayName: string;
@@ -38,7 +92,7 @@ class PossiblePowerShellExe implements IPossiblePowerShellExe {
public async exists(): Promise<boolean> {
if (this.knownToExist === undefined) {
this.knownToExist = await pfs.fileExists(this.exePath);
this.knownToExist = await pfs.SymlinkSupport.existsFile(this.exePath);
}
return this.knownToExist;
}
@@ -53,12 +107,12 @@ function getProgramFilesPath(
}
// We might be a 64-bit process looking for 32-bit program files
if (isProcess64Bit) {
if (processArch === Arch.x64) {
return env['ProgramFiles(x86)'] || null;
}
// We might be a 32-bit process looking for 64-bit program files
if (isOS64Bit) {
if (osArch === Arch.x64) {
return env.ProgramW6432 || null;
}
@@ -66,28 +120,6 @@ function getProgramFilesPath(
return null;
}
function getSystem32Path({ useAlternateBitness = false }: { useAlternateBitness?: boolean } = {}): string {
const windir: string = env.windir!;
if (!useAlternateBitness) {
// Just use the native system bitness
return path.join(windir, 'System32');
}
// We might be a 64-bit process looking for 32-bit system32
if (isProcess64Bit) {
return path.join(windir, 'SysWOW64');
}
// We might be a 32-bit process looking for 64-bit system32
if (isOS64Bit) {
return path.join(windir, 'Sysnative');
}
// We're on a 32-bit Windows, so no alternate bitness
return path.join(windir, 'System32');
}
async function findPSCoreWindowsInstallation(
{ useAlternateBitness = false, findPreview = false }:
{ useAlternateBitness?: boolean; findPreview?: boolean } = {}): Promise<IPossiblePowerShellExe | null> {
@@ -100,7 +132,7 @@ async function findPSCoreWindowsInstallation(
const powerShellInstallBaseDir = path.join(programFilesPath, 'PowerShell');
// Ensure the base directory exists
if (!await pfs.dirExists(powerShellInstallBaseDir)) {
if (!await pfs.SymlinkSupport.existsDirectory(powerShellInstallBaseDir)) {
return null;
}
@@ -142,7 +174,7 @@ async function findPSCoreWindowsInstallation(
// Now look for the file
const exePath = path.join(powerShellInstallBaseDir, item, 'pwsh.exe');
if (!await pfs.fileExists(exePath)) {
if (!await pfs.SymlinkSupport.existsFile(exePath)) {
continue;
}
@@ -169,7 +201,7 @@ async function findPSCoreMsix({ findPreview }: { findPreview?: boolean } = {}):
// Find the base directory for MSIX application exe shortcuts
const msixAppDir = path.join(env.LOCALAPPDATA, 'Microsoft', 'WindowsApps');
if (!await pfs.dirExists(msixAppDir)) {
if (!await pfs.SymlinkSupport.existsDirectory(msixAppDir)) {
return null;
}
@@ -179,11 +211,15 @@ async function findPSCoreMsix({ findPreview }: { findPreview?: boolean } = {}):
: { pwshMsixDirRegex: PwshMsixRegex, pwshMsixName: 'PowerShell (Store)' };
// We should find only one such application, so return on the first one
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);
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);
}
}
} catch (err) {
console.warn(`Unable to read MSIX directory (${msixAppDir}) because of the following error: ${err}`);
}
// If we find nothing, return null
@@ -196,33 +232,13 @@ function findPSCoreDotnetGlobalTool(): IPossiblePowerShellExe {
return new PossiblePowerShellExe(dotnetGlobalToolExePath, '.NET Core PowerShell Global Tool');
}
function findWinPS({ useAlternateBitness = false }: { useAlternateBitness?: boolean } = {}): IPossiblePowerShellExe | null {
function findWinPS(): IPossiblePowerShellExe | null {
const winPSPath = path.join(
env.windir!,
processArch === Arch.x86 && osArch !== Arch.x86 ? 'SysNative' : 'System32',
'WindowsPowerShell', 'v1.0', 'powershell.exe');
// x86 and ARM only have one WinPS on them
if (!isOS64Bit && useAlternateBitness) {
return null;
}
const systemFolderPath = getSystem32Path({ useAlternateBitness });
const winPSPath = path.join(systemFolderPath, 'WindowsPowerShell', 'v1.0', 'powershell.exe');
let displayName: string;
if (isProcess64Bit) {
displayName = useAlternateBitness
? WindowsPowerShell32BitLabel
: WindowsPowerShell64BitLabel;
} else if (isOS64Bit) {
displayName = useAlternateBitness
? WindowsPowerShell64BitLabel
: WindowsPowerShell32BitLabel;
} else {
// NOTE: ARM Windows devices also have Windows PowerShell x86 on them. There is no
// "ARM Windows PowerShell".
displayName = WindowsPowerShell32BitLabel;
}
return new PossiblePowerShellExe(winPSPath, displayName, true);
return new PossiblePowerShellExe(winPSPath, 'Windows PowerShell', true);
}
/**
@@ -276,18 +292,10 @@ async function* enumerateDefaultPowerShellInstallations(): AsyncIterable<IPossib
}
// Finally, get Windows PowerShell
// Get the natural Windows PowerShell for the process bitness
pwshExe = findWinPS();
if (pwshExe) {
yield pwshExe;
}
// Get the alternate bitness Windows PowerShell
pwshExe = findWinPS({ useAlternateBitness: true });
if (pwshExe) {
yield pwshExe;
}
}
/**

View File

@@ -5,7 +5,7 @@
import * as path from 'vs/base/common/path';
import * as fs from 'fs';
import { promisify } from 'util';
import * as pfs from 'vs/base/node/pfs';
import * as cp from 'child_process';
import * as nls from 'vs/nls';
import * as Types from 'vs/base/common/types';
@@ -456,8 +456,8 @@ export namespace win32 {
}
async function fileExists(path: string): Promise<boolean> {
if (await promisify(fs.exists)(path)) {
return !((await promisify(fs.stat)(path)).isDirectory());
if (await pfs.exists(path)) {
return !((await fs.promises.stat(path)).isDirectory());
}
return false;
}

9
src/vs/base/node/userDataPath.d.ts vendored Normal file
View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Returns the user data path to use.
*/
export function getDefaultUserDataPath(): string;

View File

@@ -0,0 +1,72 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path="../../../typings/require.d.ts" />
//@ts-check
(function () {
'use strict';
/**
* @param {typeof import('path')} path
* @param {typeof import('os')} os
* @param {string} productName
*/
function factory(path, os, productName) {
function getDefaultUserDataPath() {
// Support global VSCODE_APPDATA environment variable
let appDataPath = process.env['VSCODE_APPDATA'];
// Otherwise check per platform
if (!appDataPath) {
switch (process.platform) {
case 'win32':
appDataPath = process.env['APPDATA'];
if (!appDataPath) {
const userProfile = process.env['USERPROFILE'];
if (typeof userProfile !== 'string') {
throw new Error('Windows: Unexpected undefined %USERPROFILE% environment variable');
}
appDataPath = path.join(userProfile, 'AppData', 'Roaming');
}
break;
case 'darwin':
appDataPath = path.join(os.homedir(), 'Library', 'Application Support');
break;
case 'linux':
appDataPath = process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config');
break;
default:
throw new Error('Platform not supported');
}
}
return path.join(appDataPath, productName);
}
return {
getDefaultUserDataPath
};
}
if (typeof define === 'function') {
define(['require', 'path', 'os', 'vs/base/common/network', 'vs/base/common/resources'], function (require, /** @type {typeof import('path')} */ path, /** @type {typeof import('os')} */ os, /** @type {typeof import('../common/network')} */ network, /** @type {typeof import("../common/resources")} */ resources) {
const rootPath = resources.dirname(network.FileAccess.asFileUri('', require));
const pkg = require.__$__nodeRequire(resources.joinPath(rootPath, 'package.json').fsPath);
return factory(path, os, pkg.name);
}); // amd
} else if (typeof module === 'object' && typeof module.exports === 'object') {
const pkg = require('../../../../package.json');
const path = require('path');
const os = require('os');
module.exports = factory(path, os, pkg.name); // commonjs
} else {
throw new Error('Unknown context');
}
}());

View File

@@ -5,10 +5,10 @@
import * as nls from 'vs/nls';
import * as path from 'vs/base/common/path';
import { createWriteStream, WriteStream } from 'fs';
import { promises, createWriteStream, WriteStream } from 'fs';
import { Readable } from 'stream';
import { Sequencer, createCancelablePromise } from 'vs/base/common/async';
import { mkdirp, rimraf } from 'vs/base/node/pfs';
import { rimraf } from 'vs/base/node/pfs';
import { open as _openZip, Entry, ZipFile } from 'yauzl';
import * as yazl from 'yazl';
import { CancellationToken } from 'vs/base/common/cancellation';
@@ -86,7 +86,7 @@ function extractEntry(stream: Readable, fileName: string, mode: number, targetPa
}
});
return Promise.resolve(mkdirp(targetDirName)).then(() => new Promise<void>((c, e) => {
return Promise.resolve(promises.mkdir(targetDirName, { recursive: true })).then(() => new Promise<void>((c, e) => {
if (token.isCancellationRequested) {
return;
}
@@ -149,7 +149,7 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, tok
// directory file names end with '/'
if (/\/$/.test(fileName)) {
const targetFileName = path.join(targetPath, fileName);
last = createCancelablePromise(token => mkdirp(targetFileName).then(() => readNextEntry(token)).then(undefined, e));
last = createCancelablePromise(token => promises.mkdir(targetFileName, { recursive: true }).then(() => readNextEntry(token)).then(undefined, e));
return;
}

View File

@@ -1023,146 +1023,141 @@ export class StaticRouter<TContext = string> implements IClientRouter<TContext>
}
}
//#region createChannelReceiver / createChannelSender
/**
* Use both `createChannelReceiver` and `createChannelSender`
* for automated process <=> process communication over methods
* and events. You do not need to spell out each method on both
* sides, a proxy will take care of this.
* Use ProxyChannels to automatically wrapping and unwrapping
* services to/from IPC channels, instead of manually wrapping
* each service method and event.
*
* Rules:
* - if marshalling is enabled, only `URI` and `RegExp` is converted
* Restrictions:
* - If marshalling is enabled, only `URI` and `RegExp` is converted
* automatically for you
* - events must follow the naming convention `onUppercase`
* - Events must follow the naming convention `onUpperCase`
* - `CancellationToken` is currently not supported
* - if a context is provided, you can use `AddFirstParameterToFunctions`
* - If a context is provided, you can use `AddFirstParameterToFunctions`
* utility to signal this in the receiving side type
*/
export namespace ProxyChannel {
export interface IBaseChannelOptions {
export interface IProxyOptions {
/**
* Disables automatic marshalling of `URI`.
* If marshalling is disabled, `UriComponents`
* must be used instead.
*/
disableMarshalling?: boolean;
}
export interface IChannelReceiverOptions extends IBaseChannelOptions { }
export function createChannelReceiver(service: unknown, options?: IChannelReceiverOptions): IServerChannel {
const handler = service as { [key: string]: unknown };
const disableMarshalling = options && options.disableMarshalling;
// Buffer any event that should be supported by
// iterating over all property keys and finding them
const mapEventNameToEvent = new Map<string, Event<unknown>>();
for (const key in handler) {
if (propertyIsEvent(key)) {
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true));
}
/**
* Disables automatic marshalling of `URI`.
* If marshalling is disabled, `UriComponents`
* must be used instead.
*/
disableMarshalling?: boolean;
}
return new class implements IServerChannel {
export interface ICreateServiceChannelOptions extends IProxyOptions { }
listen<T>(_: unknown, event: string): Event<T> {
const eventImpl = mapEventNameToEvent.get(event);
if (eventImpl) {
return eventImpl as Event<T>;
export function fromService(service: unknown, options?: ICreateServiceChannelOptions): IServerChannel {
const handler = service as { [key: string]: unknown };
const disableMarshalling = options && options.disableMarshalling;
// Buffer any event that should be supported by
// iterating over all property keys and finding them
const mapEventNameToEvent = new Map<string, Event<unknown>>();
for (const key in handler) {
if (propertyIsEvent(key)) {
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true));
}
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, args?: any[]): Promise<any> {
const target = handler[command];
if (typeof target === 'function') {
return new class implements IServerChannel {
// Revive unless marshalling disabled
if (!disableMarshalling && Array.isArray(args)) {
for (let i = 0; i < args.length; i++) {
args[i] = revive(args[i]);
}
listen<T>(_: unknown, event: string): Event<T> {
const eventImpl = mapEventNameToEvent.get(event);
if (eventImpl) {
return eventImpl as Event<T>;
}
return target.apply(handler, args);
throw new Error(`Event not found: ${event}`);
}
throw new Error(`Method not found: ${command}`);
}
};
}
export interface IChannelSenderOptions extends IBaseChannelOptions {
/**
* If provided, will add the value of `context`
* to each method call to the target.
*/
context?: unknown;
/**
* If provided, will not proxy any of the properties
* that are part of the Map but rather return that value.
*/
properties?: Map<string, unknown>;
}
export function createChannelSender<T>(channel: IChannel, options?: IChannelSenderOptions): T {
const disableMarshalling = options && options.disableMarshalling;
return new Proxy({}, {
get(_target: T, propKey: PropertyKey) {
if (typeof propKey === 'string') {
// Check for predefined values
if (options?.properties?.has(propKey)) {
return options.properties.get(propKey);
}
// Event
if (propertyIsEvent(propKey)) {
return channel.listen(propKey);
}
// Function
return async function (...args: any[]) {
// Add context if any
let methodArgs: any[];
if (options && !isUndefinedOrNull(options.context)) {
methodArgs = [options.context, ...args];
} else {
methodArgs = args;
}
const result = await channel.call(propKey, methodArgs);
call(_: unknown, command: string, args?: any[]): Promise<any> {
const target = handler[command];
if (typeof target === 'function') {
// Revive unless marshalling disabled
if (!disableMarshalling) {
return revive(result);
if (!disableMarshalling && Array.isArray(args)) {
for (let i = 0; i < args.length; i++) {
args[i] = revive(args[i]);
}
}
return result;
};
return target.apply(handler, args);
}
throw new Error(`Method not found: ${command}`);
}
};
}
throw new Error(`Property not found: ${String(propKey)}`);
}
}) as T;
export interface ICreateProxyServiceOptions extends IProxyOptions {
/**
* If provided, will add the value of `context`
* to each method call to the target.
*/
context?: unknown;
/**
* If provided, will not proxy any of the properties
* that are part of the Map but rather return that value.
*/
properties?: Map<string, unknown>;
}
export function toService<T>(channel: IChannel, options?: ICreateProxyServiceOptions): T {
const disableMarshalling = options && options.disableMarshalling;
return new Proxy({}, {
get(_target: T, propKey: PropertyKey) {
if (typeof propKey === 'string') {
// Check for predefined values
if (options?.properties?.has(propKey)) {
return options.properties.get(propKey);
}
// Event
if (propertyIsEvent(propKey)) {
return channel.listen(propKey);
}
// Function
return async function (...args: any[]) {
// Add context if any
let methodArgs: any[];
if (options && !isUndefinedOrNull(options.context)) {
methodArgs = [options.context, ...args];
} else {
methodArgs = args;
}
const result = await channel.call(propKey, methodArgs);
// Revive unless marshalling disabled
if (!disableMarshalling) {
return revive(result);
}
return result;
};
}
throw new Error(`Property not found: ${String(propKey)}`);
}
}) as T;
}
function propertyIsEvent(name: string): boolean {
// Assume a property is an event if it has a form of "onSomething"
return name[0] === 'o' && name[1] === 'n' && strings.isUpperAsciiLetter(name.charCodeAt(2));
}
}
function propertyIsEvent(name: string): boolean {
// Assume a property is an event if it has a form of "onSomething"
return name[0] === 'o' && name[1] === 'n' && strings.isUpperAsciiLetter(name.charCodeAt(2));
}
//#endregion
const colorTables = [
['#2977B1', '#FC802D', '#34A13A', '#D3282F', '#9366BA'],
['#8B564C', '#E177C0', '#7F7F7F', '#BBBE3D', '#2EBECD']

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { ipcRenderer } from 'electron';
import { Event } from 'vs/base/common/event';
import { ClientConnectionEvent, IPCServer } from 'vs/base/parts/ipc/common/ipc';
import { Protocol as MessagePortProtocol } from 'vs/base/parts/ipc/common/ipc.mp';
@@ -39,6 +39,9 @@ export class Server extends IPCServer {
};
// Send one port back to the requestor
// Note: we intentionally use `electron` APIs here because
// transferables like the `MessagePort` cannot be transfered
// over preload scripts when `contextIsolation: true`
ipcRenderer.postMessage('vscode:createMessageChannelResult', nonce, [outgoingPort]);
return result;

View File

@@ -71,10 +71,8 @@ export interface IIPCOptions {
debugBrk?: number;
/**
* See https://github.com/microsoft/vscode/issues/27665
* Allows to pass in fresh execArgv to the forked process such that it doesn't inherit them from `process.execArgv`.
* e.g. Launching the extension host process with `--inspect-brk=xxx` and then forking a process from the extension host
* results in the forked process inheriting `--inspect-brk=xxx`.
* If set, starts the fork with empty execArgv. If not set, execArgv from the parent proces are inherited,
* except --inspect= and --inspect-brk= which are filtered as they would result in a port conflict.
*/
freshExecArgv?: boolean;
@@ -198,6 +196,12 @@ export class Client implements IChannelClient, IDisposable {
forkOpts.execArgv = ['--nolazy', '--inspect-brk=' + this.options.debugBrk];
}
if (forkOpts.execArgv === undefined) {
// if not set, the forked process inherits the execArgv of the parent process
// --inspect and --inspect-brk can not be inherited as the port would conflict
forkOpts.execArgv = process.execArgv.filter(a => !/^--inspect(-brk)?=/.test(a)); // remove
}
if (isMacintosh && forkOpts.env) {
// Unset `DYLD_LIBRARY_PATH`, as it leads to process crashes
// See https://github.com/microsoft/vscode/issues/105848

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, createChannelReceiver, createChannelSender } from 'vs/base/parts/ipc/common/ipc';
import { IChannel, IServerChannel, IMessagePassingProtocol, IPCServer, ClientConnectionEvent, IPCClient, ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
import { Emitter, Event } from 'vs/base/common/event';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { canceled } from 'vs/base/common/errors';
@@ -332,10 +332,10 @@ suite('Base IPC', function () {
const testServer = new TestIPCServer();
server = testServer;
server.registerChannel(TestChannelId, createChannelReceiver(service));
server.registerChannel(TestChannelId, ProxyChannel.fromService(service));
client = testServer.createConnection('client1');
ipcService = createChannelSender(client.getChannel(TestChannelId));
ipcService = ProxyChannel.toService(client.getChannel(TestChannelId));
});
teardown(function () {
@@ -398,10 +398,10 @@ suite('Base IPC', function () {
const testServer = new TestIPCServer();
server = testServer;
server.registerChannel(TestChannelId, createChannelReceiver(service));
server.registerChannel(TestChannelId, ProxyChannel.fromService(service));
client = testServer.createConnection('client1');
ipcService = createChannelSender(client.getChannel(TestChannelId), { context: 'Super Context' });
ipcService = ProxyChannel.toService(client.getChannel(TestChannelId), { context: 'Super Context' });
});
teardown(function () {

View File

@@ -11,7 +11,7 @@ suite('IPC, MessagePorts', () => {
test('message port close event', async () => {
const { port1, port2 } = new MessageChannel();
new MessagePortClient(port1, 'client1');
const client1 = new MessagePortClient(port1, 'client1');
const client2 = new MessagePortClient(port2, 'client2');
// This test ensures that Electron's API for the close event
@@ -24,5 +24,7 @@ suite('IPC, MessagePorts', () => {
client2.dispose();
assert.ok(await whenClosed);
client1.dispose();
});
});

View File

@@ -56,7 +56,7 @@ export interface IQuickInputStyles {
countBadge: ICountBadgetyles;
button: IButtonStyles;
progressBar: IProgressBarStyles;
list: IListStyles & { listInactiveFocusForeground?: Color; pickerGroupBorder?: Color; pickerGroupForeground?: Color; };
list: IListStyles & { pickerGroupBorder?: Color; pickerGroupForeground?: Color; };
}
export interface IQuickInputWidgetStyles {
@@ -1706,10 +1706,6 @@ export class QuickInputController extends Disposable {
this.ui.list.style(this.styles.list);
const content: string[] = [];
if (this.styles.list.listInactiveFocusForeground) {
content.push(`.monaco-list .monaco-list-row.focused { color: ${this.styles.list.listInactiveFocusForeground}; }`);
content.push(`.monaco-list .monaco-list-row.focused:hover { color: ${this.styles.list.listInactiveFocusForeground}; }`); // overwrite :hover style in this case!
}
if (this.styles.list.pickerGroupBorder) {
content.push(`.quick-input-list .quick-input-list-entry { border-top-color: ${this.styles.list.pickerGroupBorder}; }`);
}

View File

@@ -35,17 +35,6 @@
}
},
/**
* @param {string} channel
* @param {any} message
* @param {MessagePort[]} transfer
*/
postMessage(channel, message, transfer) {
if (validateIPC(channel)) {
ipcRenderer.postMessage(channel, message, transfer);
}
},
/**
* @param {string} channel
* @param {any[]} args
@@ -88,6 +77,33 @@
}
},
ipcMessagePort: {
/**
* @param {string} channelRequest
* @param {string} channelResponse
* @param {string} requestNonce
*/
connect(channelRequest, channelResponse, requestNonce) {
if (validateIPC(channelRequest) && validateIPC(channelResponse)) {
const responseListener = (/** @type {import('electron').IpcRendererEvent} */ e, /** @type {string} */ responseNonce) => {
// validate that the nonce from the response is the same
// as when requested. and if so, use `postMessage` to
// send the `MessagePort` safely over, even when context
// isolation is enabled
if (requestNonce === responseNonce) {
ipcRenderer.off(channelResponse, responseListener);
window.postMessage(requestNonce, '*', e.ports);
}
};
// request message port from main and await result
ipcRenderer.on(channelResponse, responseListener);
ipcRenderer.send(channelRequest, requestNonce);
}
}
},
/**
* Support for subset of methods of Electron's `webFrame` type.
*/

View File

@@ -15,10 +15,12 @@ export interface IpcRendererEvent extends Event {
// Docs: https://electronjs.org/docs/api/structures/ipc-renderer-event
/**
* A list of MessagePorts that were transferred with this message
*/
ports: MessagePort[];
// Note: API with `Transferable` intentionally commented out because you
// cannot transfer these when `contextIsolation: true`.
// /**
// * A list of MessagePorts that were transferred with this message
// */
// ports: MessagePort[];
/**
* The `IpcRenderer` instance that emitted the event originally
*/
@@ -93,20 +95,23 @@ export interface IpcRenderer {
* If you do not need a response to the message, consider using `ipcRenderer.send`.
*/
invoke(channel: string, ...args: any[]): Promise<any>;
/**
* Send a message to the main process, optionally transferring ownership of zero or
* more `MessagePort` objects.
*
* The transferred `MessagePort` objects will be available in the main process as
* `MessagePortMain` objects by accessing the `ports` property of the emitted
* event.
*
* For example:
*
* For more information on using `MessagePort` and `MessageChannel`, see the MDN
* documentation.
*/
postMessage(channel: string, message: any, transfer?: MessagePort[]): void;
// Note: API with `Transferable` intentionally commented out because you
// cannot transfer these when `contextIsolation: true`.
// /**
// * Send a message to the main process, optionally transferring ownership of zero or
// * more `MessagePort` objects.
// *
// * The transferred `MessagePort` objects will be available in the main process as
// * `MessagePortMain` objects by accessing the `ports` property of the emitted
// * event.
// *
// * For example:
// *
// * For more information on using `MessagePort` and `MessageChannel`, see the MDN
// * documentation.
// */
// postMessage(channel: string, message: any): void;
}
export interface WebFrame {

View File

@@ -3,10 +3,13 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { globals, INodeProcess, IProcessEnvironment } from 'vs/base/common/platform';
import { globals, IProcessEnvironment } from 'vs/base/common/platform';
import { ProcessMemoryInfo, CrashReporter, IpcRenderer, WebFrame } from 'vs/base/parts/sandbox/electron-sandbox/electronTypes';
export interface ISandboxNodeProcess extends INodeProcess {
/**
* In sandboxed renderers we cannot expose all of the `process` global of node.js
*/
export interface IPartialNodeProcess {
/**
* The process.platform property returns a string identifying the operating system platform
@@ -40,24 +43,6 @@ export interface ISandboxNodeProcess extends INodeProcess {
*/
readonly execPath: string;
/**
* Resolve the true process environment to use and apply it to `process.env`.
*
* There are different layers of environment that will apply:
* - `process.env`: this is the actual environment of the process before this method
* - `shellEnv` : if the program was not started from a terminal, we resolve all shell
* variables to get the same experience as if the program was started from
* a terminal (Linux, macOS)
* - `userEnv` : this is instance specific environment, e.g. if the user started the program
* from a terminal and changed certain variables
*
* The order of overwrites is `process.env` < `shellEnv` < `userEnv`.
*
* It is critical that every process awaits this method early on startup to get the right
* set of environment in `process.env`.
*/
resolveEnv(userEnv: IProcessEnvironment): Promise<void>;
/**
* A listener on the process. Only a small subset of listener types are allowed.
*/
@@ -79,6 +64,28 @@ export interface ISandboxNodeProcess extends INodeProcess {
getProcessMemoryInfo: () => Promise<ProcessMemoryInfo>;
}
export interface ISandboxNodeProcess extends IPartialNodeProcess {
/**
* A custom method we add to `process`: Resolve the true process environment to use and
* apply it to `process.env`.
*
* There are different layers of environment that will apply:
* - `process.env`: this is the actual environment of the process before this method
* - `shellEnv` : if the program was not started from a terminal, we resolve all shell
* variables to get the same experience as if the program was started from
* a terminal (Linux, macOS)
* - `userEnv` : this is instance specific environment, e.g. if the user started the program
* from a terminal and changed certain variables
*
* The order of overwrites is `process.env` < `shellEnv` < `userEnv`.
*
* It is critical that every process awaits this method early on startup to get the right
* set of environment in `process.env`.
*/
resolveEnv(userEnv: IProcessEnvironment): Promise<void>;
}
export interface ISandboxContext {
/**
@@ -87,7 +94,23 @@ export interface ISandboxContext {
sandbox: boolean;
}
export interface IpcMessagePort {
/**
* Establish a connection via `MessagePort` to a target. The main process
* will need to transfer the port over to the `channelResponse` after listening
* to `channelRequest` with a payload of `requestNonce` so that the
* source can correlate the response.
*
* The source should install a `window.on('message')` listener, ensuring `e.data`
* matches `requestNonce`, `e.source` matches `window` and then receiving the
* `MessagePort` via `e.ports[0]`.
*/
connect(channelRequest: string, channelResponse: string, requestNonce: string): void;
}
export const ipcRenderer: IpcRenderer = globals.vscode.ipcRenderer;
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;

View File

@@ -4,12 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ipcRenderer, crashReporter, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { ipcRenderer, crashReporter, webFrame, process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
suite('Sandbox', () => {
test('globals', () => {
assert.ok(ipcRenderer);
assert.ok(crashReporter);
assert.ok(webFrame);
assert.ok(typeof ipcRenderer.invoke === 'function');
assert.ok(typeof crashReporter.addExtraParameter === 'function');
assert.ok(typeof webFrame.setZoomLevel === 'function');
assert.ok(typeof process.platform === 'string');
});
});

View File

@@ -84,11 +84,13 @@ export class Storage extends Disposable implements IStorage {
private cache = new Map<string, string>();
private readonly flushDelayer = this._register(new ThrottledDelayer<void>(Storage.DEFAULT_FLUSH_DELAY));
private readonly flushDelayer = new ThrottledDelayer<void>(Storage.DEFAULT_FLUSH_DELAY);
private pendingDeletes = new Set<string>();
private pendingInserts = new Map<string, string>();
private pendingClose: Promise<void> | undefined = undefined;
private readonly whenFlushedCallbacks: Function[] = [];
constructor(
@@ -256,10 +258,15 @@ export class Storage extends Disposable implements IStorage {
}
async close(): Promise<void> {
if (this.state === StorageState.Closed) {
return; // return if already closed
if (!this.pendingClose) {
this.pendingClose = this.doClose();
}
return this.pendingClose;
}
private async doClose(): Promise<void> {
// Update state
this.state = StorageState.Closed;
@@ -312,6 +319,13 @@ export class Storage extends Disposable implements IStorage {
return new Promise(resolve => this.whenFlushedCallbacks.push(resolve));
}
dispose(): void {
this.flushDelayer.cancel(); // workaround https://github.com/microsoft/vscode/issues/116777
this.flushDelayer.dispose();
super.dispose();
}
}
export class InMemoryStorageDatabase implements IStorageDatabase {

View File

@@ -4,11 +4,12 @@
*--------------------------------------------------------------------------------------------*/
import type { Database, Statement } from 'vscode-sqlite3';
import { promises } from 'fs';
import { Event } from 'vs/base/common/event';
import { timeout } from 'vs/base/common/async';
import { mapToString, setToString } from 'vs/base/common/map';
import { basename } from 'vs/base/common/path';
import { copy, renameIgnoreError, unlink } from 'vs/base/node/pfs';
import { copy } from 'vs/base/node/pfs';
import { IStorageDatabase, IStorageItemsChangeEvent, IUpdateRequest } from 'vs/base/parts/storage/common/storage';
interface IDatabaseConnection {
@@ -186,7 +187,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase {
// Delete the existing DB. If the path does not exist or fails to
// be deleted, we do not try to recover anymore because we assume
// that the path is no longer writeable for us.
return unlink(this.path).then(() => {
return promises.unlink(this.path).then(() => {
// Re-open the DB fresh
return this.doConnect(this.path).then(recoveryConnection => {
@@ -216,7 +217,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase {
private backup(): Promise<void> {
const backupPath = this.toBackupPath(this.path);
return copy(this.path, backupPath);
return copy(this.path, backupPath, { preserveSymlinks: false });
}
private toBackupPath(path: string): string {
@@ -272,8 +273,12 @@ export class SQLiteStorageDatabase implements IStorageDatabase {
// folder is really not writeable for us.
//
try {
await unlink(path);
await renameIgnoreError(this.toBackupPath(path), path);
await promises.unlink(path);
try {
await promises.rename(this.toBackupPath(path), path);
} catch (error) {
// ignore
}
return await this.doConnect(path);
} catch (error) {

File diff suppressed because one or more lines are too long

View File

@@ -30,7 +30,7 @@ suite('dom', () => {
assert(element.classList.contains('far'));
assert(!element.classList.contains('boo'));
assert(element.classList.contains('foobar'));
assert.equal(element.className, 'foobar far');
assert.strictEqual(element.className, 'foobar far');
element = document.createElement('div');
element.className = 'foobar boo far';
@@ -39,19 +39,19 @@ suite('dom', () => {
assert(!element.classList.contains('far'));
assert(element.classList.contains('boo'));
assert(element.classList.contains('foobar'));
assert.equal(element.className, 'foobar boo');
assert.strictEqual(element.className, 'foobar boo');
element.classList.remove('boo');
assert(!element.classList.contains('far'));
assert(!element.classList.contains('boo'));
assert(element.classList.contains('foobar'));
assert.equal(element.className, 'foobar');
assert.strictEqual(element.className, 'foobar');
element.classList.remove('foobar');
assert(!element.classList.contains('far'));
assert(!element.classList.contains('boo'));
assert(!element.classList.contains('foobar'));
assert.equal(element.className, '');
assert.strictEqual(element.className, '');
});
test('removeClass should consider hyphens', function () {
@@ -83,7 +83,7 @@ suite('dom', () => {
const div = $('div');
assert(div);
assert(div instanceof HTMLElement);
assert.equal(div.tagName, 'DIV');
assert.strictEqual(div.tagName, 'DIV');
assert(!div.firstChild);
});
@@ -91,42 +91,42 @@ suite('dom', () => {
const div = $('div#foo');
assert(div);
assert(div instanceof HTMLElement);
assert.equal(div.tagName, 'DIV');
assert.equal(div.id, 'foo');
assert.strictEqual(div.tagName, 'DIV');
assert.strictEqual(div.id, 'foo');
});
test('should buld nodes with class-name', () => {
const div = $('div.foo');
assert(div);
assert(div instanceof HTMLElement);
assert.equal(div.tagName, 'DIV');
assert.equal(div.className, 'foo');
assert.strictEqual(div.tagName, 'DIV');
assert.strictEqual(div.className, 'foo');
});
test('should build nodes with attributes', () => {
let div = $('div', { class: 'test' });
assert.equal(div.className, 'test');
assert.strictEqual(div.className, 'test');
div = $('div', undefined);
assert.equal(div.className, '');
assert.strictEqual(div.className, '');
});
test('should build nodes with children', () => {
let div = $('div', undefined, $('span', { id: 'demospan' }));
let firstChild = div.firstChild as HTMLElement;
assert.equal(firstChild.tagName, 'SPAN');
assert.equal(firstChild.id, 'demospan');
assert.strictEqual(firstChild.tagName, 'SPAN');
assert.strictEqual(firstChild.id, 'demospan');
div = $('div', undefined, 'hello');
assert.equal(div.firstChild && div.firstChild.textContent, 'hello');
assert.strictEqual(div.firstChild && div.firstChild.textContent, 'hello');
});
test('should build nodes with text children', () => {
let div = $('div', undefined, 'foobar');
let firstChild = div.firstChild as HTMLElement;
assert.equal(firstChild.tagName, undefined);
assert.equal(firstChild.textContent, 'foobar');
assert.strictEqual(firstChild.tagName, undefined);
assert.strictEqual(firstChild.textContent, 'foobar');
});
});
});

View File

@@ -9,53 +9,53 @@ import { sha1Hex } from 'vs/base/browser/hash';
suite('Hash', () => {
test('string', () => {
assert.equal(hash('hello'), hash('hello'));
assert.notEqual(hash('hello'), hash('world'));
assert.notEqual(hash('hello'), hash('olleh'));
assert.notEqual(hash('hello'), hash('Hello'));
assert.notEqual(hash('hello'), hash('Hello '));
assert.notEqual(hash('h'), hash('H'));
assert.notEqual(hash('-'), hash('_'));
assert.strictEqual(hash('hello'), hash('hello'));
assert.notStrictEqual(hash('hello'), hash('world'));
assert.notStrictEqual(hash('hello'), hash('olleh'));
assert.notStrictEqual(hash('hello'), hash('Hello'));
assert.notStrictEqual(hash('hello'), hash('Hello '));
assert.notStrictEqual(hash('h'), hash('H'));
assert.notStrictEqual(hash('-'), hash('_'));
});
test('number', () => {
assert.equal(hash(1), hash(1));
assert.notEqual(hash(0), hash(1));
assert.notEqual(hash(1), hash(-1));
assert.notEqual(hash(0x12345678), hash(0x123456789));
assert.strictEqual(hash(1), hash(1));
assert.notStrictEqual(hash(0), hash(1));
assert.notStrictEqual(hash(1), hash(-1));
assert.notStrictEqual(hash(0x12345678), hash(0x123456789));
});
test('boolean', () => {
assert.equal(hash(true), hash(true));
assert.notEqual(hash(true), hash(false));
assert.strictEqual(hash(true), hash(true));
assert.notStrictEqual(hash(true), hash(false));
});
test('array', () => {
assert.equal(hash([1, 2, 3]), hash([1, 2, 3]));
assert.equal(hash(['foo', 'bar']), hash(['foo', 'bar']));
assert.equal(hash([]), hash([]));
assert.equal(hash([]), hash(new Array()));
assert.notEqual(hash(['foo', 'bar']), hash(['bar', 'foo']));
assert.notEqual(hash(['foo', 'bar']), hash(['bar', 'foo', null]));
assert.notEqual(hash(['foo', 'bar', null]), hash(['bar', 'foo', null]));
assert.notEqual(hash(['foo', 'bar']), hash(['bar', 'foo', undefined]));
assert.notEqual(hash(['foo', 'bar', undefined]), hash(['bar', 'foo', undefined]));
assert.notEqual(hash(['foo', 'bar', null]), hash(['foo', 'bar', undefined]));
assert.strictEqual(hash([1, 2, 3]), hash([1, 2, 3]));
assert.strictEqual(hash(['foo', 'bar']), hash(['foo', 'bar']));
assert.strictEqual(hash([]), hash([]));
assert.strictEqual(hash([]), hash(new Array()));
assert.notStrictEqual(hash(['foo', 'bar']), hash(['bar', 'foo']));
assert.notStrictEqual(hash(['foo', 'bar']), hash(['bar', 'foo', null]));
assert.notStrictEqual(hash(['foo', 'bar', null]), hash(['bar', 'foo', null]));
assert.notStrictEqual(hash(['foo', 'bar']), hash(['bar', 'foo', undefined]));
assert.notStrictEqual(hash(['foo', 'bar', undefined]), hash(['bar', 'foo', undefined]));
assert.notStrictEqual(hash(['foo', 'bar', null]), hash(['foo', 'bar', undefined]));
});
test('object', () => {
assert.equal(hash({}), hash({}));
assert.equal(hash({}), hash(Object.create(null)));
assert.equal(hash({ 'foo': 'bar' }), hash({ 'foo': 'bar' }));
assert.equal(hash({ 'foo': 'bar', 'foo2': undefined }), hash({ 'foo2': undefined, 'foo': 'bar' }));
assert.notEqual(hash({ 'foo': 'bar' }), hash({ 'foo': 'bar2' }));
assert.notEqual(hash({}), hash([]));
assert.strictEqual(hash({}), hash({}));
assert.strictEqual(hash({}), hash(Object.create(null)));
assert.strictEqual(hash({ 'foo': 'bar' }), hash({ 'foo': 'bar' }));
assert.strictEqual(hash({ 'foo': 'bar', 'foo2': undefined }), hash({ 'foo2': undefined, 'foo': 'bar' }));
assert.notStrictEqual(hash({ 'foo': 'bar' }), hash({ 'foo': 'bar2' }));
assert.notStrictEqual(hash({}), hash([]));
});
test('array - unexpected collision', function () {
const a = hash([undefined, undefined, undefined, undefined, undefined]);
const b = hash([undefined, undefined, 'HHHHHH', [{ line: 0, character: 0 }, { line: 0, character: 0 }], undefined]);
assert.notEqual(a, b);
assert.notStrictEqual(a, b);
});
test('all different', () => {
@@ -65,9 +65,9 @@ suite('Hash', () => {
];
const hashes: number[] = candidates.map(hash);
for (let i = 0; i < hashes.length; i++) {
assert.equal(hashes[i], hash(candidates[i])); // verify that repeated invocation returns the same hash
assert.strictEqual(hashes[i], hash(candidates[i])); // verify that repeated invocation returns the same hash
for (let k = i + 1; k < hashes.length; k++) {
assert.notEqual(hashes[i], hashes[k], `Same hash ${hashes[i]} for ${JSON.stringify(candidates[i])} and ${JSON.stringify(candidates[k])}`);
assert.notStrictEqual(hashes[i], hashes[k], `Same hash ${hashes[i]} for ${JSON.stringify(candidates[i])} and ${JSON.stringify(candidates[k])}`);
}
}
});
@@ -79,11 +79,11 @@ suite('Hash', () => {
const hash = new StringSHA1();
hash.update(str);
let actual = hash.digest();
assert.equal(actual, expected);
assert.strictEqual(actual, expected);
// Test with crypto.subtle
actual = await sha1Hex(str);
assert.equal(actual, expected);
assert.strictEqual(actual, expected);
}
test('sha1-1', () => {

View File

@@ -2,6 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
@@ -13,50 +14,50 @@ suite('HighlightedLabel', () => {
});
test('empty label', function () {
assert.equal(label.element.innerHTML, '');
assert.strictEqual(label.element.innerHTML, '');
});
test('no decorations', function () {
label.set('hello');
assert.equal(label.element.innerHTML, '<span>hello</span>');
assert.strictEqual(label.element.innerHTML, '<span>hello</span>');
});
test('escape html', function () {
label.set('hel<lo');
assert.equal(label.element.innerHTML, '<span>hel&lt;lo</span>');
assert.strictEqual(label.element.innerHTML, '<span>hel&lt;lo</span>');
});
test('everything highlighted', function () {
label.set('hello', [{ start: 0, end: 5 }]);
assert.equal(label.element.innerHTML, '<span class="highlight">hello</span>');
assert.strictEqual(label.element.innerHTML, '<span class="highlight">hello</span>');
});
test('beginning highlighted', function () {
label.set('hellothere', [{ start: 0, end: 5 }]);
assert.equal(label.element.innerHTML, '<span class="highlight">hello</span><span>there</span>');
assert.strictEqual(label.element.innerHTML, '<span class="highlight">hello</span><span>there</span>');
});
test('ending highlighted', function () {
label.set('goodbye', [{ start: 4, end: 7 }]);
assert.equal(label.element.innerHTML, '<span>good</span><span class="highlight">bye</span>');
assert.strictEqual(label.element.innerHTML, '<span>good</span><span class="highlight">bye</span>');
});
test('middle highlighted', function () {
label.set('foobarfoo', [{ start: 3, end: 6 }]);
assert.equal(label.element.innerHTML, '<span>foo</span><span class="highlight">bar</span><span>foo</span>');
assert.strictEqual(label.element.innerHTML, '<span>foo</span><span class="highlight">bar</span><span>foo</span>');
});
test('escapeNewLines', () => {
let highlights = [{ start: 0, end: 5 }, { start: 7, end: 9 }, { start: 11, end: 12 }];// before,after,after
let escaped = HighlightedLabel.escapeNewLines('ACTION\r\n_TYPE2', highlights);
assert.equal(escaped, 'ACTION\u23CE_TYPE2');
assert.deepEqual(highlights, [{ start: 0, end: 5 }, { start: 6, end: 8 }, { start: 10, end: 11 }]);
assert.strictEqual(escaped, 'ACTION\u23CE_TYPE2');
assert.deepStrictEqual(highlights, [{ start: 0, end: 5 }, { start: 6, end: 8 }, { start: 10, end: 11 }]);
highlights = [{ start: 5, end: 9 }, { start: 11, end: 12 }];//overlap,after
escaped = HighlightedLabel.escapeNewLines('ACTION\r\n_TYPE2', highlights);
assert.equal(escaped, 'ACTION\u23CE_TYPE2');
assert.deepEqual(highlights, [{ start: 5, end: 8 }, { start: 10, end: 11 }]);
assert.strictEqual(escaped, 'ACTION\u23CE_TYPE2');
assert.deepStrictEqual(highlights, [{ start: 5, end: 8 }, { start: 10, end: 11 }]);
});
});

View File

@@ -3,45 +3,45 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
import * as assert from 'assert';
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
suite('renderLabelWithIcons', () => {
test('no icons', () => {
const result = renderLabelWithIcons(' hello World .');
assert.equal(elementsToString(result), ' hello World .');
assert.strictEqual(elementsToString(result), ' hello World .');
});
test('icons only', () => {
const result = renderLabelWithIcons('$(alert)');
assert.equal(elementsToString(result), '<span class="codicon codicon-alert"></span>');
assert.strictEqual(elementsToString(result), '<span class="codicon codicon-alert"></span>');
});
test('icon and non-icon strings', () => {
const result = renderLabelWithIcons(` $(alert) Unresponsive`);
assert.equal(elementsToString(result), ' <span class="codicon codicon-alert"></span> Unresponsive');
assert.strictEqual(elementsToString(result), ' <span class="codicon codicon-alert"></span> Unresponsive');
});
test('multiple icons', () => {
const result = renderLabelWithIcons('$(check)$(error)');
assert.equal(elementsToString(result), '<span class="codicon codicon-check"></span><span class="codicon codicon-error"></span>');
assert.strictEqual(elementsToString(result), '<span class="codicon codicon-check"></span><span class="codicon codicon-error"></span>');
});
test('escaped icons', () => {
const result = renderLabelWithIcons('\\$(escaped)');
assert.equal(elementsToString(result), '$(escaped)');
assert.strictEqual(elementsToString(result), '$(escaped)');
});
test('icon with animation', () => {
const result = renderLabelWithIcons('$(zip~anim)');
assert.equal(elementsToString(result), '<span class="codicon codicon-zip codicon-modifier-anim"></span>');
assert.strictEqual(elementsToString(result), '<span class="codicon codicon-zip codicon-modifier-anim"></span>');
});
const elementsToString = (elements: Array<HTMLElement | string>): string => {

View File

@@ -9,20 +9,20 @@ import { layout, LayoutAnchorPosition } from 'vs/base/browser/ui/contextview/con
suite('Contextview', function () {
test('layout', () => {
assert.equal(layout(200, 20, { offset: 0, size: 0, position: LayoutAnchorPosition.Before }), 0);
assert.equal(layout(200, 20, { offset: 50, size: 0, position: LayoutAnchorPosition.Before }), 50);
assert.equal(layout(200, 20, { offset: 200, size: 0, position: LayoutAnchorPosition.Before }), 180);
assert.strictEqual(layout(200, 20, { offset: 0, size: 0, position: LayoutAnchorPosition.Before }), 0);
assert.strictEqual(layout(200, 20, { offset: 50, size: 0, position: LayoutAnchorPosition.Before }), 50);
assert.strictEqual(layout(200, 20, { offset: 200, size: 0, position: LayoutAnchorPosition.Before }), 180);
assert.equal(layout(200, 20, { offset: 0, size: 0, position: LayoutAnchorPosition.After }), 0);
assert.equal(layout(200, 20, { offset: 50, size: 0, position: LayoutAnchorPosition.After }), 30);
assert.equal(layout(200, 20, { offset: 200, size: 0, position: LayoutAnchorPosition.After }), 180);
assert.strictEqual(layout(200, 20, { offset: 0, size: 0, position: LayoutAnchorPosition.After }), 0);
assert.strictEqual(layout(200, 20, { offset: 50, size: 0, position: LayoutAnchorPosition.After }), 30);
assert.strictEqual(layout(200, 20, { offset: 200, size: 0, position: LayoutAnchorPosition.After }), 180);
assert.equal(layout(200, 20, { offset: 0, size: 50, position: LayoutAnchorPosition.Before }), 50);
assert.equal(layout(200, 20, { offset: 50, size: 50, position: LayoutAnchorPosition.Before }), 100);
assert.equal(layout(200, 20, { offset: 150, size: 50, position: LayoutAnchorPosition.Before }), 130);
assert.strictEqual(layout(200, 20, { offset: 0, size: 50, position: LayoutAnchorPosition.Before }), 50);
assert.strictEqual(layout(200, 20, { offset: 50, size: 50, position: LayoutAnchorPosition.Before }), 100);
assert.strictEqual(layout(200, 20, { offset: 150, size: 50, position: LayoutAnchorPosition.Before }), 130);
assert.equal(layout(200, 20, { offset: 0, size: 50, position: LayoutAnchorPosition.After }), 50);
assert.equal(layout(200, 20, { offset: 50, size: 50, position: LayoutAnchorPosition.After }), 30);
assert.equal(layout(200, 20, { offset: 150, size: 50, position: LayoutAnchorPosition.After }), 130);
assert.strictEqual(layout(200, 20, { offset: 0, size: 50, position: LayoutAnchorPosition.After }), 50);
assert.strictEqual(layout(200, 20, { offset: 50, size: 50, position: LayoutAnchorPosition.After }), 30);
assert.strictEqual(layout(200, 20, { offset: 150, size: 50, position: LayoutAnchorPosition.After }), 130);
});
});

View File

@@ -807,4 +807,187 @@ suite('Async', () => {
assert.strictEqual(deferred.isRejected, true);
});
});
suite('Promises.allSettled', () => {
test('resolves', async () => {
const p1 = Promise.resolve(1);
const p2 = async.timeout(1).then(() => 2);
const p3 = async.timeout(2).then(() => 3);
const result = await async.Promises.allSettled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], { status: 'fulfilled', value: 1 });
assert.deepStrictEqual(result[1], { status: 'fulfilled', value: 2 });
assert.deepStrictEqual(result[2], { status: 'fulfilled', value: 3 });
});
test('resolves in order', async () => {
const p1 = async.timeout(2).then(() => 1);
const p2 = async.timeout(1).then(() => 2);
const p3 = Promise.resolve(3);
const result = await async.Promises.allSettled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], { status: 'fulfilled', value: 1 });
assert.deepStrictEqual(result[1], { status: 'fulfilled', value: 2 });
assert.deepStrictEqual(result[2], { status: 'fulfilled', value: 3 });
});
test('rejects', async () => {
const p1 = Promise.reject(1);
const p2Error = new Error('2');
const p2 = async.timeout(1).then(() => { throw p2Error; });
const p3Error = new Error('3');
const p3 = async.timeout(2).then(() => { throw p3Error; });
const result = await async.Promises.allSettled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], { status: 'rejected', reason: 1 });
assert.deepStrictEqual(result[1], { status: 'rejected', reason: p2Error });
assert.deepStrictEqual(result[2], { status: 'rejected', reason: p3Error });
});
test('rejects in order', async () => {
const p1Error = new Error('1');
const p1 = async.timeout(2).then(() => { throw p1Error; });
const p2Error = new Error('2');
const p2 = async.timeout(1).then(() => { throw p2Error; });
const p3 = Promise.reject(3);
const result = await async.Promises.allSettled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], { status: 'rejected', reason: p1Error });
assert.deepStrictEqual(result[1], { status: 'rejected', reason: p2Error });
assert.deepStrictEqual(result[2], { status: 'rejected', reason: 3 });
});
test('resolves & rejects', async () => {
const p1 = Promise.resolve(1);
const p2Error = new Error('2');
const p2 = async.timeout(1).then(() => { throw p2Error; });
const p3 = async.timeout(2).then(() => 3);
const result = await async.Promises.allSettled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], { status: 'fulfilled', value: 1 });
assert.deepStrictEqual(result[1], { status: 'rejected', reason: p2Error });
assert.deepStrictEqual(result[2], { status: 'fulfilled', value: 3 });
});
test('resolves & rejects in order', async () => {
const p1Error = new Error('2');
const p1 = async.timeout(1).then(() => { throw p1Error; });
const p2 = async.timeout(2).then(() => 2);
const p3 = Promise.resolve(3);
const result = await async.Promises.allSettled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], { status: 'rejected', reason: p1Error });
assert.deepStrictEqual(result[1], { status: 'fulfilled', value: 2 });
assert.deepStrictEqual(result[2], { status: 'fulfilled', value: 3 });
});
test('can empty', async () => {
const result = await async.Promises.allSettled<number>([]);
assert.strictEqual(result.length, 0);
});
});
suite('Promises.settled', () => {
test('resolves', async () => {
const p1 = Promise.resolve(1);
const p2 = async.timeout(1).then(() => 2);
const p3 = async.timeout(2).then(() => 3);
const result = await async.Promises.settled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], 1);
assert.deepStrictEqual(result[1], 2);
assert.deepStrictEqual(result[2], 3);
});
test('resolves in order', async () => {
const p1 = async.timeout(2).then(() => 1);
const p2 = async.timeout(1).then(() => 2);
const p3 = Promise.resolve(3);
const result = await async.Promises.settled<number>([p1, p2, p3]);
assert.strictEqual(result.length, 3);
assert.deepStrictEqual(result[0], 1);
assert.deepStrictEqual(result[1], 2);
assert.deepStrictEqual(result[2], 3);
});
test('rejects with first error but handles all promises (all errors)', async () => {
const p1 = Promise.reject(1);
let p2Handled = false;
const p2Error = new Error('2');
const p2 = async.timeout(1).then(() => {
p2Handled = true;
throw p2Error;
});
let p3Handled = false;
const p3Error = new Error('3');
const p3 = async.timeout(2).then(() => {
p3Handled = true;
throw p3Error;
});
let error: Error | undefined = undefined;
try {
await async.Promises.settled<number>([p1, p2, p3]);
} catch (e) {
error = e;
}
assert.ok(error);
assert.notStrictEqual(error, p2Error);
assert.notStrictEqual(error, p3Error);
assert.ok(p2Handled);
assert.ok(p3Handled);
});
test('rejects with first error but handles all promises (1 error)', async () => {
const p1 = Promise.resolve(1);
let p2Handled = false;
const p2Error = new Error('2');
const p2 = async.timeout(1).then(() => {
p2Handled = true;
throw p2Error;
});
let p3Handled = false;
const p3 = async.timeout(2).then(() => {
p3Handled = true;
return 3;
});
let error: Error | undefined = undefined;
try {
await async.Promises.settled<number>([p1, p2, p3]);
} catch (e) {
error = e;
}
assert.strictEqual(error, p2Error);
assert.ok(p2Handled);
assert.ok(p3Handled);
});
});
});

View File

@@ -3,10 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { Event, Emitter, EventBufferer, EventMultiplexer, IWaitUntil, PauseableEmitter, AsyncEmitter } from 'vs/base/common/event';
import { Event, Emitter, EventBufferer, EventMultiplexer, PauseableEmitter } from 'vs/base/common/event';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import * as Errors from 'vs/base/common/errors';
import { timeout } from 'vs/base/common/async';
import { errorHandler, setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { AsyncEmitter, IWaitUntil, timeout } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
namespace Samples {
@@ -57,7 +57,7 @@ suite('Event', function () {
// unhook listener
subscription.dispose();
doc.setText('boo');
assert.equal(counter.count, 2);
assert.strictEqual(counter.count, 2);
});
@@ -80,7 +80,7 @@ suite('Event', function () {
subscription.dispose();
doc.setText('boo');
assert.equal(counter.count, 2);
assert.strictEqual(counter.count, 2);
});
test('Emitter, store', function () {
@@ -100,7 +100,7 @@ suite('Event', function () {
subscription.dispose();
doc.setText('boo');
assert.equal(counter.count, 2);
assert.strictEqual(counter.count, 2);
});
test('onFirstAdd|onLastRemove', () => {
@@ -112,25 +112,25 @@ suite('Event', function () {
onLastListenerRemove() { lastCount += 1; }
});
assert.equal(firstCount, 0);
assert.equal(lastCount, 0);
assert.strictEqual(firstCount, 0);
assert.strictEqual(lastCount, 0);
let subscription = a.event(function () { });
assert.equal(firstCount, 1);
assert.equal(lastCount, 0);
assert.strictEqual(firstCount, 1);
assert.strictEqual(lastCount, 0);
subscription.dispose();
assert.equal(firstCount, 1);
assert.equal(lastCount, 1);
assert.strictEqual(firstCount, 1);
assert.strictEqual(lastCount, 1);
subscription = a.event(function () { });
assert.equal(firstCount, 2);
assert.equal(lastCount, 1);
assert.strictEqual(firstCount, 2);
assert.strictEqual(lastCount, 1);
});
test('throwingListener', () => {
const origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
Errors.setUnexpectedErrorHandler(() => null);
const origErrorHandler = errorHandler.getUnexpectedErrorHandler();
setUnexpectedErrorHandler(() => null);
try {
let a = new Emitter<undefined>();
@@ -143,10 +143,10 @@ suite('Event', function () {
hit = true;
});
a.fire(undefined);
assert.equal(hit, true);
assert.strictEqual(hit, true);
} finally {
Errors.setUnexpectedErrorHandler(origErrorHandler);
setUnexpectedErrorHandler(origErrorHandler);
}
});
@@ -162,15 +162,15 @@ suite('Event', function () {
let reg2 = emitter.event(listener, context);
emitter.fire(undefined);
assert.equal(counter, 2);
assert.strictEqual(counter, 2);
reg1.dispose();
emitter.fire(undefined);
assert.equal(counter, 3);
assert.strictEqual(counter, 3);
reg2.dispose();
emitter.fire(undefined);
assert.equal(counter, 3);
assert.strictEqual(counter, 3);
});
test('Debounce Event', function (done: () => void) {
@@ -192,9 +192,9 @@ suite('Event', function () {
assert.ok(keys, 'was not expecting keys.');
if (count === 1) {
doc.setText('4');
assert.deepEqual(keys, ['1', '2', '3']);
assert.deepStrictEqual(keys, ['1', '2', '3']);
} else if (count === 2) {
assert.deepEqual(keys, ['4']);
assert.deepStrictEqual(keys, ['4']);
done();
}
});
@@ -217,7 +217,7 @@ suite('Event', function () {
emitter.fire();
await timeout(1);
assert.equal(calls, 1);
assert.strictEqual(calls, 1);
});
test('Debounce Event - leading', async function () {
@@ -234,7 +234,7 @@ suite('Event', function () {
emitter.fire();
emitter.fire();
await timeout(1);
assert.equal(calls, 2);
assert.strictEqual(calls, 2);
});
test('Debounce Event - leading reset', async function () {
@@ -248,7 +248,7 @@ suite('Event', function () {
emitter.fire(1);
await timeout(1);
assert.deepEqual(calls, [1, 1]);
assert.deepStrictEqual(calls, [1, 1]);
});
test('Emitter - In Order Delivery', function () {
@@ -258,7 +258,7 @@ suite('Event', function () {
if (event === 'e1') {
a.fire('e2');
// assert that all events are delivered at this point
assert.deepEqual(listener2Events, ['e1', 'e2']);
assert.deepStrictEqual(listener2Events, ['e1', 'e2']);
}
});
a.event(function listener2(event) {
@@ -267,7 +267,7 @@ suite('Event', function () {
a.fire('e1');
// assert that all events are delivered in order
assert.deepEqual(listener2Events, ['e1', 'e2']);
assert.deepStrictEqual(listener2Events, ['e1', 'e2']);
});
});
@@ -283,9 +283,9 @@ suite('AsyncEmitter', function () {
let emitter = new AsyncEmitter<E>();
emitter.event(e => {
assert.equal(e.foo, true);
assert.equal(e.bar, 1);
assert.equal(typeof e.waitUntil, 'function');
assert.strictEqual(e.foo, true);
assert.strictEqual(e.bar, 1);
assert.strictEqual(typeof e.waitUntil, 'function');
});
emitter.fireAsync({ foo: true, bar: 1, }, CancellationToken.None);
@@ -303,20 +303,20 @@ suite('AsyncEmitter', function () {
emitter.event(e => {
e.waitUntil(timeout(10).then(_ => {
assert.equal(globalState, 0);
assert.strictEqual(globalState, 0);
globalState += 1;
}));
});
emitter.event(e => {
e.waitUntil(timeout(1).then(_ => {
assert.equal(globalState, 1);
assert.strictEqual(globalState, 1);
globalState += 1;
}));
});
await emitter.fireAsync({ foo: true }, CancellationToken.None);
assert.equal(globalState, 2);
assert.strictEqual(globalState, 2);
});
test('sequential, in-order delivery', async function () {
@@ -332,7 +332,7 @@ suite('AsyncEmitter', function () {
e.waitUntil(timeout(10).then(async _ => {
if (e.foo === 1) {
await emitter.fireAsync({ foo: 2 }, CancellationToken.None);
assert.deepEqual(events, [1, 2]);
assert.deepStrictEqual(events, [1, 2]);
done = true;
}
}));
@@ -349,8 +349,8 @@ suite('AsyncEmitter', function () {
});
test('catch errors', async function () {
const origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
Errors.setUnexpectedErrorHandler(() => null);
const origErrorHandler = errorHandler.getUnexpectedErrorHandler();
setUnexpectedErrorHandler(() => null);
interface E extends IWaitUntil {
foo: boolean;
@@ -367,16 +367,17 @@ suite('AsyncEmitter', function () {
emitter.event(e => {
globalState += 1;
e.waitUntil(timeout(10));
e.waitUntil(timeout(20).then(() => globalState++)); // multiple `waitUntil` are supported and awaited on
});
await emitter.fireAsync({ foo: true }, CancellationToken.None).then(() => {
assert.equal(globalState, 2);
assert.strictEqual(globalState, 3);
}).catch(e => {
console.log(e);
assert.ok(false);
});
Errors.setUnexpectedErrorHandler(origErrorHandler);
setUnexpectedErrorHandler(origErrorHandler);
});
});
@@ -390,7 +391,7 @@ suite('PausableEmitter', function () {
emitter.fire(1);
emitter.fire(2);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
});
test('pause/resume - no merge', function () {
@@ -400,17 +401,17 @@ suite('PausableEmitter', function () {
emitter.event(e => data.push(e));
emitter.fire(1);
emitter.fire(2);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.pause();
emitter.fire(3);
emitter.fire(4);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.resume();
assert.deepEqual(data, [1, 2, 3, 4]);
assert.deepStrictEqual(data, [1, 2, 3, 4]);
emitter.fire(5);
assert.deepEqual(data, [1, 2, 3, 4, 5]);
assert.deepStrictEqual(data, [1, 2, 3, 4, 5]);
});
test('pause/resume - merge', function () {
@@ -420,18 +421,18 @@ suite('PausableEmitter', function () {
emitter.event(e => data.push(e));
emitter.fire(1);
emitter.fire(2);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.pause();
emitter.fire(3);
emitter.fire(4);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.resume();
assert.deepEqual(data, [1, 2, 7]);
assert.deepStrictEqual(data, [1, 2, 7]);
emitter.fire(5);
assert.deepEqual(data, [1, 2, 7, 5]);
assert.deepStrictEqual(data, [1, 2, 7, 5]);
});
test('double pause/resume', function () {
@@ -441,22 +442,22 @@ suite('PausableEmitter', function () {
emitter.event(e => data.push(e));
emitter.fire(1);
emitter.fire(2);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.pause();
emitter.pause();
emitter.fire(3);
emitter.fire(4);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.resume();
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.resume();
assert.deepEqual(data, [1, 2, 3, 4]);
assert.deepStrictEqual(data, [1, 2, 3, 4]);
emitter.resume();
assert.deepEqual(data, [1, 2, 3, 4]);
assert.deepStrictEqual(data, [1, 2, 3, 4]);
});
test('resume, no pause', function () {
@@ -466,11 +467,11 @@ suite('PausableEmitter', function () {
emitter.event(e => data.push(e));
emitter.fire(1);
emitter.fire(2);
assert.deepEqual(data, [1, 2]);
assert.deepStrictEqual(data, [1, 2]);
emitter.resume();
emitter.fire(3);
assert.deepEqual(data, [1, 2, 3]);
assert.deepStrictEqual(data, [1, 2, 3]);
});
test('nested pause', function () {
@@ -493,16 +494,16 @@ suite('PausableEmitter', function () {
emitter.pause();
emitter.fire(1);
emitter.fire(2);
assert.deepEqual(data, []);
assert.deepStrictEqual(data, []);
emitter.resume();
assert.deepEqual(data, [1, 1]); // paused after first event
assert.deepStrictEqual(data, [1, 1]); // paused after first event
emitter.resume();
assert.deepEqual(data, [1, 1, 2, 2]); // remaing event delivered
assert.deepStrictEqual(data, [1, 1, 2, 2]); // remaing event delivered
emitter.fire(3);
assert.deepEqual(data, [1, 1, 2, 2, 3, 3]);
assert.deepStrictEqual(data, [1, 1, 2, 2, 3, 3]);
});
});
@@ -518,13 +519,13 @@ suite('Event utils', () => {
const event = bufferer.wrapEvent(emitter.event);
const listener = event(counter.onEvent, counter);
assert.equal(counter.count, 0);
assert.strictEqual(counter.count, 0);
emitter.fire();
assert.equal(counter.count, 1);
assert.strictEqual(counter.count, 1);
emitter.fire();
assert.equal(counter.count, 2);
assert.strictEqual(counter.count, 2);
emitter.fire();
assert.equal(counter.count, 3);
assert.strictEqual(counter.count, 3);
listener.dispose();
});
@@ -536,20 +537,20 @@ suite('Event utils', () => {
const event = bufferer.wrapEvent(emitter.event);
const listener = event(counter.onEvent, counter);
assert.equal(counter.count, 0);
assert.strictEqual(counter.count, 0);
emitter.fire();
assert.equal(counter.count, 1);
assert.strictEqual(counter.count, 1);
bufferer.bufferEvents(() => {
emitter.fire();
assert.equal(counter.count, 1);
assert.strictEqual(counter.count, 1);
emitter.fire();
assert.equal(counter.count, 1);
assert.strictEqual(counter.count, 1);
});
assert.equal(counter.count, 3);
assert.strictEqual(counter.count, 3);
emitter.fire();
assert.equal(counter.count, 4);
assert.strictEqual(counter.count, 4);
listener.dispose();
});
@@ -563,20 +564,20 @@ suite('Event utils', () => {
const listener2 = Event.once(emitter.event)(() => counter2++);
const listener3 = Event.once(emitter.event)(() => counter3++);
assert.equal(counter1, 0);
assert.equal(counter2, 0);
assert.equal(counter3, 0);
assert.strictEqual(counter1, 0);
assert.strictEqual(counter2, 0);
assert.strictEqual(counter3, 0);
listener3.dispose();
emitter.fire();
assert.equal(counter1, 1);
assert.equal(counter2, 1);
assert.equal(counter3, 0);
assert.strictEqual(counter1, 1);
assert.strictEqual(counter2, 1);
assert.strictEqual(counter3, 0);
emitter.fire();
assert.equal(counter1, 2);
assert.equal(counter2, 1);
assert.equal(counter3, 0);
assert.strictEqual(counter1, 2);
assert.strictEqual(counter2, 1);
assert.strictEqual(counter3, 0);
listener1.dispose();
listener2.dispose();
@@ -591,10 +592,10 @@ suite('Event utils', () => {
const event = Event.fromPromise(Promise.resolve(null));
event(() => count++);
assert.equal(count, 0);
assert.strictEqual(count, 0);
await timeout(10);
assert.equal(count, 1);
assert.strictEqual(count, 1);
});
test('should emit when done - setTimeout', async () => {
@@ -604,9 +605,9 @@ suite('Event utils', () => {
const event = Event.fromPromise(promise);
event(() => count++);
assert.equal(count, 0);
assert.strictEqual(count, 0);
await promise;
assert.equal(count, 1);
assert.strictEqual(count, 1);
});
});
@@ -646,14 +647,14 @@ suite('Event utils', () => {
assert.deepEqual(result, []);
const listener = bufferedEvent(num => result.push(num));
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
emitter.fire(4);
assert.deepEqual(result, [1, 2, 3, 4]);
assert.deepStrictEqual(result, [1, 2, 3, 4]);
listener.dispose();
emitter.fire(5);
assert.deepEqual(result, [1, 2, 3, 4]);
assert.deepStrictEqual(result, [1, 2, 3, 4]);
});
test('should buffer events on next tick', async () => {
@@ -668,14 +669,14 @@ suite('Event utils', () => {
assert.deepEqual(result, []);
const listener = bufferedEvent(num => result.push(num));
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
await timeout(10);
emitter.fire(4);
assert.deepEqual(result, [1, 2, 3, 4]);
assert.deepStrictEqual(result, [1, 2, 3, 4]);
listener.dispose();
emitter.fire(5);
assert.deepEqual(result, [1, 2, 3, 4]);
assert.deepStrictEqual(result, [1, 2, 3, 4]);
});
test('should fire initial buffer events', () => {
@@ -690,7 +691,7 @@ suite('Event utils', () => {
assert.deepEqual(result, []);
bufferedEvent(num => result.push(num));
assert.deepEqual(result, [-2, -1, 0, 1, 2, 3]);
assert.deepStrictEqual(result, [-2, -1, 0, 1, 2, 3]);
});
});
@@ -704,10 +705,10 @@ suite('Event utils', () => {
const e1 = new Emitter<number>();
m.add(e1.event);
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
e1.fire(0);
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
});
test('multiplexer dispose works', () => {
@@ -718,16 +719,16 @@ suite('Event utils', () => {
const e1 = new Emitter<number>();
m.add(e1.event);
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
e1.fire(0);
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
m.dispose();
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
e1.fire(0);
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
});
test('event dispose works', () => {
@@ -738,16 +739,16 @@ suite('Event utils', () => {
const e1 = new Emitter<number>();
m.add(e1.event);
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
e1.fire(0);
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
e1.dispose();
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
e1.fire(0);
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
});
test('mutliplexer event dispose works', () => {
@@ -758,16 +759,16 @@ suite('Event utils', () => {
const e1 = new Emitter<number>();
const l1 = m.add(e1.event);
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
e1.fire(0);
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
l1.dispose();
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
e1.fire(0);
assert.deepEqual(result, [0]);
assert.deepStrictEqual(result, [0]);
});
test('hot start works', () => {
@@ -785,7 +786,7 @@ suite('Event utils', () => {
e1.fire(1);
e2.fire(2);
e3.fire(3);
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
});
test('cold start works', () => {
@@ -804,7 +805,7 @@ suite('Event utils', () => {
e1.fire(1);
e2.fire(2);
e3.fire(3);
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
});
test('late add works', () => {
@@ -825,7 +826,7 @@ suite('Event utils', () => {
m.add(e3.event);
e3.fire(3);
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
});
test('add dispose works', () => {
@@ -845,15 +846,15 @@ suite('Event utils', () => {
const e3 = new Emitter<number>();
const l3 = m.add(e3.event);
e3.fire(3);
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
l3.dispose();
e3.fire(4);
assert.deepEqual(result, [1, 2, 3]);
assert.deepStrictEqual(result, [1, 2, 3]);
e2.fire(4);
e1.fire(5);
assert.deepEqual(result, [1, 2, 3, 4, 5]);
assert.deepStrictEqual(result, [1, 2, 3, 4, 5]);
});
});
@@ -864,31 +865,31 @@ suite('Event utils', () => {
const result: number[] = [];
const listener = event(num => result.push(num));
assert.deepEqual(result, []);
assert.deepStrictEqual(result, []);
emitter.fire(1);
assert.deepEqual(result, [1]);
assert.deepStrictEqual(result, [1]);
emitter.fire(2);
assert.deepEqual(result, [1, 2]);
assert.deepStrictEqual(result, [1, 2]);
emitter.fire(2);
assert.deepEqual(result, [1, 2]);
assert.deepStrictEqual(result, [1, 2]);
emitter.fire(1);
assert.deepEqual(result, [1, 2, 1]);
assert.deepStrictEqual(result, [1, 2, 1]);
emitter.fire(1);
assert.deepEqual(result, [1, 2, 1]);
assert.deepStrictEqual(result, [1, 2, 1]);
emitter.fire(3);
assert.deepEqual(result, [1, 2, 1, 3]);
assert.deepStrictEqual(result, [1, 2, 1, 3]);
emitter.fire(3);
assert.deepEqual(result, [1, 2, 1, 3]);
assert.deepStrictEqual(result, [1, 2, 1, 3]);
emitter.fire(3);
assert.deepEqual(result, [1, 2, 1, 3]);
assert.deepStrictEqual(result, [1, 2, 1, 3]);
listener.dispose();
});

View File

@@ -5,7 +5,7 @@
import * as assert from 'assert';
import * as extpath from 'vs/base/common/extpath';
import * as platform from 'vs/base/common/platform';
import { isWindows } from 'vs/base/common/platform';
import { CharCode } from 'vs/base/common/charCode';
suite('Paths', () => {
@@ -32,7 +32,7 @@ suite('Paths', () => {
assert.strictEqual(extpath.getRoot('file://foo'), '');
});
(!platform.isWindows ? test.skip : test)('isUNC', () => {
(!isWindows ? test.skip : test)('isUNC', () => {
assert.ok(!extpath.isUNC('foo'));
assert.ok(!extpath.isUNC('/foo'));
assert.ok(!extpath.isUNC('\\foo'));
@@ -51,7 +51,7 @@ suite('Paths', () => {
assert.ok(!extpath.isValidBasename('/test.txt'));
assert.ok(!extpath.isValidBasename('\\test.txt'));
if (platform.isWindows) {
if (isWindows) {
assert.ok(!extpath.isValidBasename('aux'));
assert.ok(!extpath.isValidBasename('Aux'));
assert.ok(!extpath.isValidBasename('LPT0'));
@@ -72,7 +72,7 @@ suite('Paths', () => {
});
test('sanitizeFilePath', () => {
if (platform.isWindows) {
if (isWindows) {
assert.strictEqual(extpath.sanitizeFilePath('.', 'C:\\the\\cwd'), 'C:\\the\\cwd');
assert.strictEqual(extpath.sanitizeFilePath('', 'C:\\the\\cwd'), 'C:\\the\\cwd');
@@ -108,7 +108,7 @@ suite('Paths', () => {
});
test('isRootOrDriveLetter', () => {
if (platform.isWindows) {
if (isWindows) {
assert.ok(extpath.isRootOrDriveLetter('c:'));
assert.ok(extpath.isRootOrDriveLetter('D:'));
assert.ok(extpath.isRootOrDriveLetter('D:/'));
@@ -122,7 +122,7 @@ suite('Paths', () => {
});
test('hasDriveLetter', () => {
if (platform.isWindows) {
if (isWindows) {
assert.ok(extpath.hasDriveLetter('c:'));
assert.ok(extpath.hasDriveLetter('D:'));
assert.ok(extpath.hasDriveLetter('D:/'));
@@ -136,7 +136,7 @@ suite('Paths', () => {
});
test('getDriveLetter', () => {
if (platform.isWindows) {
if (isWindows) {
assert.strictEqual(extpath.getDriveLetter('c:'), 'c');
assert.strictEqual(extpath.getDriveLetter('D:'), 'D');
assert.strictEqual(extpath.getDriveLetter('D:/'), 'D');

View File

@@ -4,13 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as scorer from 'vs/base/common/fuzzyScorer';
import { IItemAccessor, FuzzyScore, FuzzyScore2, IItemScore, prepareQuery, scoreFuzzy, scoreFuzzy2, scoreItemFuzzy, compareItemsByFuzzyScore, pieceToQuery } from 'vs/base/common/fuzzyScorer';
import { URI } from 'vs/base/common/uri';
import { basename, dirname, sep, posix, win32 } from 'vs/base/common/path';
import { isWindows } from 'vs/base/common/platform';
import { Schemas } from 'vs/base/common/network';
class ResourceAccessorClass implements scorer.IItemAccessor<URI> {
class ResourceAccessorClass implements IItemAccessor<URI> {
getItemLabel(resource: URI): string {
return basename(resource.fsPath);
@@ -27,7 +27,7 @@ class ResourceAccessorClass implements scorer.IItemAccessor<URI> {
const ResourceAccessor = new ResourceAccessorClass();
class ResourceWithSlashAccessorClass implements scorer.IItemAccessor<URI> {
class ResourceWithSlashAccessorClass implements IItemAccessor<URI> {
getItemLabel(resource: URI): string {
return basename(resource.fsPath);
@@ -44,7 +44,7 @@ class ResourceWithSlashAccessorClass implements scorer.IItemAccessor<URI> {
const ResourceWithSlashAccessor = new ResourceWithSlashAccessorClass();
class ResourceWithBackslashAccessorClass implements scorer.IItemAccessor<URI> {
class ResourceWithBackslashAccessorClass implements IItemAccessor<URI> {
getItemLabel(resource: URI): string {
return basename(resource.fsPath);
@@ -61,7 +61,7 @@ class ResourceWithBackslashAccessorClass implements scorer.IItemAccessor<URI> {
const ResourceWithBackslashAccessor = new ResourceWithBackslashAccessorClass();
class NullAccessorClass implements scorer.IItemAccessor<URI> {
class NullAccessorClass implements IItemAccessor<URI> {
getItemLabel(resource: URI): string {
return undefined!;
@@ -76,24 +76,24 @@ class NullAccessorClass implements scorer.IItemAccessor<URI> {
}
}
function _doScore(target: string, query: string, fuzzy: boolean): scorer.FuzzyScore {
const preparedQuery = scorer.prepareQuery(query);
function _doScore(target: string, query: string, fuzzy: boolean): FuzzyScore {
const preparedQuery = prepareQuery(query);
return scorer.scoreFuzzy(target, preparedQuery.normalized, preparedQuery.normalizedLowercase, fuzzy);
return scoreFuzzy(target, preparedQuery.normalized, preparedQuery.normalizedLowercase, fuzzy);
}
function _doScore2(target: string, query: string, matchOffset: number = 0): scorer.FuzzyScore2 {
const preparedQuery = scorer.prepareQuery(query);
function _doScore2(target: string, query: string, matchOffset: number = 0): FuzzyScore2 {
const preparedQuery = prepareQuery(query);
return scorer.scoreFuzzy2(target, preparedQuery, 0, matchOffset);
return scoreFuzzy2(target, preparedQuery, 0, matchOffset);
}
function scoreItem<T>(item: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor<T>): scorer.IItemScore {
return scorer.scoreItemFuzzy(item, scorer.prepareQuery(query), fuzzy, accessor, Object.create(null));
function scoreItem<T>(item: T, query: string, fuzzy: boolean, accessor: IItemAccessor<T>): IItemScore {
return scoreItemFuzzy(item, prepareQuery(query), fuzzy, accessor, Object.create(null));
}
function compareItemsByScore<T>(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: scorer.IItemAccessor<T>): number {
return scorer.compareItemsByFuzzyScore(itemA, itemB, scorer.prepareQuery(query), fuzzy, accessor, Object.create(null));
function compareItemsByScore<T>(itemA: T, itemB: T, query: string, fuzzy: boolean, accessor: IItemAccessor<T>): number {
return compareItemsByFuzzyScore(itemA, itemB, prepareQuery(query), fuzzy, accessor, Object.create(null));
}
const NullAccessor = new NullAccessorClass();
@@ -103,7 +103,7 @@ suite('Fuzzy Scorer', () => {
test('score (fuzzy)', function () {
const target = 'HeLlo-World';
const scores: scorer.FuzzyScore[] = [];
const scores: FuzzyScore[] = [];
scores.push(_doScore(target, 'HelLo-World', true)); // direct case match
scores.push(_doScore(target, 'hello-world', true)); // direct mix-case match
scores.push(_doScore(target, 'HW', true)); // direct case prefix (multiple)
@@ -1071,16 +1071,16 @@ suite('Fuzzy Scorer', () => {
});
test('prepareQuery', () => {
assert.strictEqual(scorer.prepareQuery(' f*a ').normalized, 'fa');
assert.strictEqual(scorer.prepareQuery('model Tester.ts').original, 'model Tester.ts');
assert.strictEqual(scorer.prepareQuery('model Tester.ts').originalLowercase, 'model Tester.ts'.toLowerCase());
assert.strictEqual(scorer.prepareQuery('model Tester.ts').normalized, 'modelTester.ts');
assert.strictEqual(scorer.prepareQuery('Model Tester.ts').normalizedLowercase, 'modeltester.ts');
assert.strictEqual(scorer.prepareQuery('ModelTester.ts').containsPathSeparator, false);
assert.strictEqual(scorer.prepareQuery('Model' + sep + 'Tester.ts').containsPathSeparator, true);
assert.strictEqual(prepareQuery(' f*a ').normalized, 'fa');
assert.strictEqual(prepareQuery('model Tester.ts').original, 'model Tester.ts');
assert.strictEqual(prepareQuery('model Tester.ts').originalLowercase, 'model Tester.ts'.toLowerCase());
assert.strictEqual(prepareQuery('model Tester.ts').normalized, 'modelTester.ts');
assert.strictEqual(prepareQuery('Model Tester.ts').normalizedLowercase, 'modeltester.ts');
assert.strictEqual(prepareQuery('ModelTester.ts').containsPathSeparator, false);
assert.strictEqual(prepareQuery('Model' + sep + 'Tester.ts').containsPathSeparator, true);
// with spaces
let query = scorer.prepareQuery('He*llo World');
let query = prepareQuery('He*llo World');
assert.strictEqual(query.original, 'He*llo World');
assert.strictEqual(query.normalized, 'HelloWorld');
assert.strictEqual(query.normalizedLowercase, 'HelloWorld'.toLowerCase());
@@ -1092,13 +1092,13 @@ suite('Fuzzy Scorer', () => {
assert.strictEqual(query.values?.[1].normalized, 'World');
assert.strictEqual(query.values?.[1].normalizedLowercase, 'World'.toLowerCase());
let restoredQuery = scorer.pieceToQuery(query.values!);
let restoredQuery = pieceToQuery(query.values!);
assert.strictEqual(restoredQuery.original, query.original);
assert.strictEqual(restoredQuery.values?.length, query.values?.length);
assert.strictEqual(restoredQuery.containsPathSeparator, query.containsPathSeparator);
// with spaces that are empty
query = scorer.prepareQuery(' Hello World ');
query = prepareQuery(' Hello World ');
assert.strictEqual(query.original, ' Hello World ');
assert.strictEqual(query.originalLowercase, ' Hello World '.toLowerCase());
assert.strictEqual(query.normalized, 'HelloWorld');
@@ -1115,19 +1115,19 @@ suite('Fuzzy Scorer', () => {
// Path related
if (isWindows) {
assert.strictEqual(scorer.prepareQuery('C:\\some\\path').pathNormalized, 'C:\\some\\path');
assert.strictEqual(scorer.prepareQuery('C:\\some\\path').normalized, 'C:\\some\\path');
assert.strictEqual(scorer.prepareQuery('C:\\some\\path').containsPathSeparator, true);
assert.strictEqual(scorer.prepareQuery('C:/some/path').pathNormalized, 'C:\\some\\path');
assert.strictEqual(scorer.prepareQuery('C:/some/path').normalized, 'C:\\some\\path');
assert.strictEqual(scorer.prepareQuery('C:/some/path').containsPathSeparator, true);
assert.strictEqual(prepareQuery('C:\\some\\path').pathNormalized, 'C:\\some\\path');
assert.strictEqual(prepareQuery('C:\\some\\path').normalized, 'C:\\some\\path');
assert.strictEqual(prepareQuery('C:\\some\\path').containsPathSeparator, true);
assert.strictEqual(prepareQuery('C:/some/path').pathNormalized, 'C:\\some\\path');
assert.strictEqual(prepareQuery('C:/some/path').normalized, 'C:\\some\\path');
assert.strictEqual(prepareQuery('C:/some/path').containsPathSeparator, true);
} else {
assert.strictEqual(scorer.prepareQuery('/some/path').pathNormalized, '/some/path');
assert.strictEqual(scorer.prepareQuery('/some/path').normalized, '/some/path');
assert.strictEqual(scorer.prepareQuery('/some/path').containsPathSeparator, true);
assert.strictEqual(scorer.prepareQuery('\\some\\path').pathNormalized, '/some/path');
assert.strictEqual(scorer.prepareQuery('\\some\\path').normalized, '/some/path');
assert.strictEqual(scorer.prepareQuery('\\some\\path').containsPathSeparator, true);
assert.strictEqual(prepareQuery('/some/path').pathNormalized, '/some/path');
assert.strictEqual(prepareQuery('/some/path').normalized, '/some/path');
assert.strictEqual(prepareQuery('/some/path').containsPathSeparator, true);
assert.strictEqual(prepareQuery('\\some\\path').pathNormalized, '/some/path');
assert.strictEqual(prepareQuery('\\some\\path').normalized, '/some/path');
assert.strictEqual(prepareQuery('\\some\\path').containsPathSeparator, true);
}
});

View File

@@ -2,9 +2,10 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as path from 'vs/base/common/path';
import * as glob from 'vs/base/common/glob';
import { sep } from 'vs/base/common/path';
import { isWindows } from 'vs/base/common/platform';
suite('Glob', () => {
@@ -952,7 +953,7 @@ suite('Glob', () => {
}
function nativeSep(slashPath: string): string {
return slashPath.replace(/\//g, path.sep);
return slashPath.replace(/\//g, sep);
}
test('relative pattern - glob star', function () {

View File

@@ -5,7 +5,7 @@
import * as assert from 'assert';
import { IMatch } from 'vs/base/common/filters';
import { matchesFuzzyIconAware, parseLabelWithIcons, IParsedLabelWithIcons, stripIcons } from 'vs/base/common/iconLabels';
import { matchesFuzzyIconAware, parseLabelWithIcons, IParsedLabelWithIcons, stripIcons, escapeIcons, markdownEscapeEscapedIcons } from 'vs/base/common/iconLabels';
export interface IIconFilter {
// Returns null if word doesn't match.
@@ -66,9 +66,23 @@ suite('Icon Labels', () => {
});
test('stripIcons', () => {
assert.equal(stripIcons('Hello World'), 'Hello World');
assert.equal(stripIcons('$(Hello World'), '$(Hello World');
assert.equal(stripIcons('$(Hello) World'), ' World');
assert.equal(stripIcons('$(Hello) W$(oi)rld'), ' Wrld');
assert.strictEqual(stripIcons('Hello World'), 'Hello World');
assert.strictEqual(stripIcons('$(Hello World'), '$(Hello World');
assert.strictEqual(stripIcons('$(Hello) World'), ' World');
assert.strictEqual(stripIcons('$(Hello) W$(oi)rld'), ' Wrld');
});
test('escapeIcons', () => {
assert.strictEqual(escapeIcons('Hello World'), 'Hello World');
assert.strictEqual(escapeIcons('$(Hello World'), '$(Hello World');
assert.strictEqual(escapeIcons('$(Hello) World'), '\\$(Hello) World');
assert.strictEqual(escapeIcons('\\$(Hello) W$(oi)rld'), '\\$(Hello) W\\$(oi)rld');
});
test('markdownEscapeEscapedIcons', () => {
assert.strictEqual(markdownEscapeEscapedIcons('Hello World'), 'Hello World');
assert.strictEqual(markdownEscapeEscapedIcons('$(Hello) World'), '$(Hello) World');
assert.strictEqual(markdownEscapeEscapedIcons('\\$(Hello) World'), '\\\\$(Hello) World');
});
});

View File

@@ -25,4 +25,11 @@ suite('Iterable', function () {
assert.equal(Iterable.first(customIterable), 'one'); // fresh
});
test('equals', () => {
assert.strictEqual(Iterable.equals([1, 2], [1, 2]), true);
assert.strictEqual(Iterable.equals([1, 2], [1]), false);
assert.strictEqual(Iterable.equals([1], [1, 2]), false);
assert.strictEqual(Iterable.equals([2, 1], [1, 2]), false);
});
});

Some files were not shown because too many files have changed in this diff Show More